可见性修饰符

类、对象、接口、构造器、函数、属性以及它们的 setter 都有 可见性修饰符。(getter 的可见性与属性一致)。Kotlin 中有四个可见性修饰符:privateprotectedinternalpublic。默认的可见性(如果没有显示指明修饰符)是 public

下面会解释修饰符如何作用于不同类型的声明域(different types of declaring scopes)。

函数、属性,类、对象以及接口可以声明在“最顶层”,也就是说,直接在包内。

  1. // file name: example.kt
  2. package foo
  3. fun baz() {}
  4. class Bar {}
  • 如果没有指明任何可见性修饰符,默认为 public,意味着你的定义在任何地方都是可见的。
  • 如果用 private 来标记声明,那么只在声明所在的文件内可见。
  • 如果标记为 internal,只要是同一个模块,都可见。
  • protected 对于顶层声明不可用。

注意:如果要使用其他包的可见顶层声明,任然需要导入。

例子:

  1. // file name: example.kt
  2. package foo
  3. private fun foo() {} // visible inside example.kt
  4. public var bar: Int = 5 // property is visible everywhere
  5. private set // setter is visible only in example.kt
  6. internal val baz = 6 // visible inside the same module

类和接口

对于声明在类中的成员:

  • private 意味着只在这个类中可见(包含类所有的成员);
  • protected —— 与 private 一致并且在子类中也可见;
  • internal —— 与类的可见性一致,但是仅限于当前模块内;
  • public —— 可见性与类一致。

Java 用户要注意:内部类的私有成员对外部类不可见。

如果覆写了一个 protected 成员并且没有显示指明可见性的话,覆写的成员的可见性也会是 protected

例子:

  1. open class Outer {
  2. private val a = 1
  3. protected open val b = 2
  4. internal val c = 3
  5. val d = 4 // public by default
  6. protected class Nested {
  7. public val e: Int = 5
  8. }
  9. }
  10. class Subclass : Outer() {
  11. // a is not visible
  12. // b, c, and d are visible
  13. // Nested and e are visible
  14. override val d = 5 // 'b' is protected
  15. }
  16. class Unrelated(o: Outer) {
  17. // o.a, o.b are not visible
  18. // o.c and o.d are visible (same module)
  19. // Outer.Nested is not visible, and Nested::e is not visible either
  20. }

构造器

如果要指明类构造器的可见性,可以使用如下语法(注意,需要写明 constructor 关键字):

  1. class C private constructor(a: Int) { ... }

这里的构造器是私有。默认情况下,所有的构造器都是 public,只要是类可见的地方,构造器都可见(例如,internal 类的构造器只在同样的模块内可见)。

局部声明

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

模块

可见性修饰符 internal 表示成员在同样的模块中是可见的。更具体一点来说,一个模块就是编译在一起的 Kotlin 文件集合:

  • 一个 IntelliJ IDEA 模块;
  • 一个 Maven 工程;
  • 一个 Gradle source set(有一个例外,test 代码集合可以访问 main 的内部声明);
  • 通过调用一次 Ant 任务编译的文件集合