Kotlin专题「十一」(可见性修饰符(private、protected、internal、public))

前言:不要假装很努力,因为结果不会陪你演戏。
一、概述 ??类,对象,接口,构造函数,函数,属性及其setter可以具有可见性修饰符(getter始终具有与属性相同的可见性)。在 Kotlin 中有四个可见性修饰符:private,protected,internal和public。默认可见性是public(在没有显式修饰符时)。
下面将会给大家讲解修饰符如何在应用声明作用域的不同类型。
这里先来介绍一下类的几种修饰符,它包含 classModifier 和 accessModifier
1.1 classModifier
  • open: ??? 表示类可继承,类默认是final的;
  • final: ??? 表示类不可继承,默认属性;
  • abstract: ? 表示抽象类;
  • enum:??? 表示枚举类;
  • annotation: 表示注解类;
1.2 accessModifier_
  • public:??? 表示公有,范围最大,所有调用的地方可见,具有最大的访问权限,可以被其他所有类访问,如果没有声明修饰符则系统会默认使用这个修饰符;
  • private:?? 表示私有,范围最小,仅在同一文件可见,只能被自己访问和修改;
  • protected:? 表示私有+子类,同一个文件中或者子类可见,自己和子类及同一包中的类可以访问,不能用于顶层声明;
  • internal:?? 表示模块,同一个模块中可见。
二、使用 2.1 顶层声明
函数,属性和类,对象和接口可以在顶层top-level声明,即直接在包中声明:
//文件名:ModifierActivity.kt package com.suming.kotlindemo.blog fun send() { //默认public修饰 //TODO }class ModifierActivity { //默认public修饰 }

如下图:
Kotlin专题「十一」(可见性修饰符(private、protected、internal、public))
文章图片

  • 如果没有指定任何可见修饰符,默认为 public,所以这些声明将随处可见;
  • 如果将声明标记为私有 private ,那么它将只在包含该声明的文件中可见;
  • 如果将声明标记为内部 internal ,它在同一个模块中随处可见;
  • protected 对顶级top-level声明不可用。
注意:要使用来自另一个包的可见顶级 top-level 声明,您仍然应该导入它。
举个例子:
//文件名:ModifierActivity.kt package com.suming.kotlindemo.blogprivate fun share() {//只在 ModifierActivity.kt 文件中可见 //TODO }public var type: Int = 5 //public修饰,公共的,属性在哪都可见 private set//setter方法私有,仅在 ModifierActivity.kt 文件中可见internal val name: String = "Kotlin" //在同一个模块内可见//protected var sign = 0 //报错,protected不能用于顶级声明中class ModifierActivity { }

2.2 类
对于在类中声明的成员:
  • public:?? 表示任何看到已声明类的客户端都会看到它的公共成员;
  • private:?? 表示只在类内部可见(包括其所有成员);
  • protected:? 表示只在当前类和子类中可见;
  • internal: ? 表示这个模块中任何看到声明类的客户端都看到了它的internal内部成员。
注意:在 Kotlin 中,外部类不会看到其内部类的私有成员。
如果你重写了一个 protected 修饰的成员而没有显式指定它的可见性,那么重写的成员也将具有protected的可见性。举个例子:
//基类 open class Outer { private val numA = 0 protected open val numB = 1 internal val numC = 2 public val numD = 3//内部类 protected class Inner { public val numE = 4 private val numF = 5 //不可以被Outer访问 } }//子类 class Student : Outer() { //numA 不可见 //numB、numC、numD 可见 //Inner 和 numE 可见override val numB: Int = 10 // numB 是 protected 修饰的,同类和子类可见//使用如下: fun foo() { //numA //报错,不可见 numB //可见 numC //可见 numD //可见 Inner() //可见 Inner().numE //可见 } }class People(val outer: Outer) { //outer.numA, outer.numB 不可见 //outer.numC, outer.numD 可见,属于同一个Module //Outer.Inner不可见,Inner::numE也不可见//使用如下: fun foo() { //outer.numA //报错,不可见 //outer.numB //报错,不可见outer.numC //可见 outer.numD //可见//Outer.Inner //报错,不可见 //Inner::numE //报错,不可见 } }

(2)构造函数
要指定类的主构造函数的可见性,使用以下语法(注意有可见性修饰符时, constructor 关键字不能隐藏):
class Dragon private constructor(name: String) { //私有构造函数 //辅助构造函数 constructor(name: String, type: Int) : this(name) { //private val numA = 0 //报错,本地变量不能有可见性修饰符 //protected val numB = 1 //报错 //internal val numC = 2 //报错 //public val numD = 3 //报错val numE = 4 //正确 } }

这里的构造函数是私有的。默认情况下,所有的构造函数是 public 的,这意味着它们在类可见的任何地方都是可见的(例如,一个内部类的构造函数只在同一个模块中可见)。辅助构造函数{}中的属性和本地变量一样,不能有可见性修饰符。
(3)局部声明
注意:本地(局部)变量,函数和类不能有可见修饰符。
class Rabbit { fun foo() { //public var textView = TextView() //报错,本地变量不能有可见性修饰符 //private var textView = TextView() //报错 //protected var textView = TextView() //报错 //internal var textView = TextView() //报错//public fun invite() {} //报错,本地函数不能有可见性修饰符 //private fun invite() {} //报错 //protected fun invite() {} //报错 //internal fun invite() {} //报错//public class Goose {} //报错,局部类不能有可见性修饰符 //private class Goose {} //报错 //protected class Goose {} //报错 //internal class Goose {} //报错 } }

【Kotlin专题「十一」(可见性修饰符(private、protected、internal、public))】可以看到,本地(局部)变量,函数和类不能有 publicprivateprotectedinternal可见修饰符。
2.3 接口
接口中的属性只能用 public 修饰,函数只能用 publicprivate 修饰,但是 private 修饰的函数不能被重写。要使用接口中的属性和方法则需要在实现中重写(可以参考我上一篇文章)。
interface baseInterface { //接口中的属性默认是抽象的,private,protected,internal都不能与抽象 abstract 共用 //private val numA: Int //报错 //protected val numB: Int //报错 //internal val numC: Int //报错 public val numD: Intpublic fun share() {//能被重写 numD }//private 可以修饰方法,并且可以使用接口中的属性,但是不能被子类重写 private fun share2() { numD }//protected fun share3() //报错,protected不能修饰接口中的函数//internal fun share4() //报错,protected不能修饰接口中的函数 }//实现类,要使用接口的属性则需要重写 class Chicken : baseInterface { override val numD: Int = 0 override fun share() { super.share() } }

对于在接口声明,因为接口中的属性默认是抽象的,即 abstract 修饰的,然而 privateprotectedinternal都不能与 abstract 修饰符共用,所以属性只能用 public修饰。
接口中的函数默认是 public 修饰的,private修饰的函数则不能被子类重写,protectedinternal都不能修饰接口中的函数。
2.4 模块
internal 修饰符表示该成员在同一个模块中可见。更具体的说,模块是一组共同编译的 Kotlin 文件:
  • 一个IntelliJ IDEA模块;
  • 一个Maven项目;
  • Gradle源集(test 源集可以访问 main 的内部声明除外);
  • 使用< kotlinc > Ant任务的一次调用编译的一组文件。
总的来说,可见性修饰符 Kotlin 与 Java 还是有不同之处:
  • 1.Kotlin 的四种修饰符:public、private、protected和internal;Java 的四种修饰符:public、privavte、protected和default(即不使用任何修饰符);
  • 2.Kotlin 中默认的修饰符为public,Java 中默认的修饰符为default。
至此,本文结束!

源码地址:https://github.com/FollowExcellence/KotlinDemo-master

请尊重原创者版权,转载请标明出处:https://blog.csdn.net/m0_37796683/article/details/107987178 谢谢!

    推荐阅读