目录

Kotlin系列(十六):访问权限之可见性修饰符

一、前言:

  • 可见性修饰符也就是控制类、或者成员的访问权限。
  • 通过可见性修饰符的使用,我们可以控制哪些类或成员可以被访问,可以被继承、可以被重写等。
  • 可见性修饰符对于安全性而言其是非常重要的实施手段。
  • 接下来我们将一起来学习Kotlin中的可见性修饰符。

二、可见性修饰符的概念

  • 类、对象、接口、构造函数、方法、属性和它们的 setter 都可以有 可见性修饰符。 (getter 总是与属性有着相同的可见性。)
  • 在 Kotlin 中有这四个可见性修饰符:privateprotectedinternalpublic
  • 如果没有显式指定修饰符的话,默认可见性是 public

Kotlin中的可见性修饰符 与 Java 主要有些不同,主要不同点如下:

  • 1、 Kotlin 抛弃了 Java 中的默认访问控制符default,添加了 internal 访问控制符;

  • 2、 Kotlin 中的访问控制符的修饰范围扩大到 包级元素,包括包级属性和包级函数;

  • 3、 Kotlin 对 privateprotected 的访问范围进行了一些修改。

java默认修饰符补充:

  • Java中类的成员如果在定义的时候指定访问修饰时,其默认为default。

  • default对于同一个包中的其他类相当于公开(public),对于不是同一个包中的其他类相当于私有(private)。

  • 受保护(protected)对子类相当于公开,对不是同一包中的没有父子关系的类相当于私有。

  • Ok,继续会到我们的Kotlin中来,下面我们将根据声明作用域的不同来解释。

三、包级别上使用修饰符

  • 函数、属性和类、对象和接口可以在顶层声明,即直接在包内:

      package foo
    
      fun baz() {}
      class Bar {}
    
  • 如果你不指定任何可见性修饰符,默认为 public,这意味着你的声明将随处可见;
  • 如果你声明为 private,它只会在声明它的文件内可见;
  • 如果你声明为 internal,它会在相同模块内随处可见;
  • protected 不适用于顶层声明。
  • 注意:要使用另一包中可见的顶层声明,仍需将其导入进来。

internal

  • 我们上面说了,internal修饰的只能在模块内可见,如果没搭建过大型项目,模块这个概念大家可能比较陌生,下面我们来看看官方给出的模块的概念。
模块
  • 可见性修饰符 internal 意味着该成员只在相同模块内可见。更具体地说, 一个模块是编译在一起的一套 Kotlin 文件:
  • 一个 IntelliJ IDEA 模块;
  • 一个 Maven 项目;
  • 一个 Gradle 源集;
  • 一次 <kotlinc> Ant 任务执行所编译的一套文件。
  • Ok,了解了模块的概念后我们继续来看下各个修饰符的作用范围。

  • 示例代码如下:

      // 文件名:example.kt
      package foo
    
      private fun foo() {} // 在 example.kt 内可见
    
      public var bar: Int = 5 // 该属性随处可见
      private set         // setter 只在 example.kt 内可见
    
      internal val baz = 6    // 相同模块内可见
    

四、类和接口上的可见性修饰符

  • 对于类内部声明的成员:
  • private 意味着只在这个类内部(包含其所有成员)可见;
  • protected—— 和 private一样 ,但protected修饰的在子类中也是可见。
  • internal —— 本模块内可见
  • public —— 随处可见
  • 注意 与Java不同的是:Kotlin 中外部类不能访问内部类的 private 成员。

  • 如果你覆盖一个 protected 成员并且没有显式指定其可见性,该成员还会是 protected 可见性。

  • 例子:

      open class Outer {
      		private val a = 1
      		protected open val b = 2
      		internal val c = 3
      		val d = 4  // 默认 public
    
      		protected class Nested {
      				public val e: Int = 5
      		}
      }
    
      class Subclass : Outer() {
      		// a 不可见
      		// b、c、d 可见
      		// Nested 和 e 可见
    
      		override val b = 5   // “b”为 protected
      }
    
      class Unrelated(o: Outer) {
      		// o.a、o.b 不可见
      		// o.c 和 o.d 可见(相同模块)
      		// Outer.Nested 不可见,Nested::e 也不可见
      }
    

五、构造函数上的可见性修饰符

  • 要指定一个类的的主构造函数的可见性,使用以下语法(注意你需要添加一个显式 constructor{:.keyword} 关键字):

      class C private constructor(a: Int) { …… }
    
  • 这里的构造函数是私有的。默认情况下,所有构造函数都是 public,这实际上等于类可见的地方它就可见(即 一个 internal 类的构造函数只能在相同模块内可见).

六、局部声明

  • 局部变量、函数和类不能有可见性修饰符。

七、总结

  • 本次我们学习了Kotlin的可见性修饰符,合理运用能给我们的程序带来更好的安全性。
  • 同时我们也了解了其和java的不同以及模块的概念。