Kotlin系列之可见性修饰符

今天一起来看看Kotlin中的可见性修饰符。

Java的访问修饰符

首先也是简单先说一下Java中的可见性修饰符相关的概念,这里用一个表格来对比着看一下。

访问修饰符 子类 其他包
public
protected x
默认 x x
private x x x

上面看出Java的默认访问权限是包访问权限,其他的访问控制修饰都是Java基础知识了,这里不再赘述。

Kotlin的访问修饰符

Kotlin的访问修饰符与Java中有些类似,但也存在一定的差异。在Kotlin中,没有包访问权限这这种可见性控制,Kotlin中只是将包作为一种组织代码的方式,类似于命名空间。

同时,Kotlin提供了一种新的修饰符internal,表示只在模块内可见。这里的模块指一组一起编译的Kotlin文件。可能是一个IDEA模块,也可能是一个项目。这种模块级别的访问控制可以真正做到将代码的具体实现封装在模块内部,实现了真正的封装,而Java的默认包控制权限,可能会有人将代码写在同一个包下,而破坏这种封装性。

在Kotlin中protected修饰符与Java中不同,由于没有包访问控制的概念,所以在Kotlin中,protected就只是控制父类与子类之间的访问权限控制。

Kotlin中的publicprotectedprivate修饰符与Java中的用法是一样的。但是在Kotlin中默认的访问修饰符是public,也就是如果你不显式指定修饰符,默认就是public的。下面上代码看一下。

Kotlin代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package kt

open class View{
private val num = 1;

private fun privateFun(){
println("我是私有方法")
}

protected fun protectedFun(){
println("我是protected方法")
}

internal fun internalFun(){
println("我是internal方法")
}

public fun publicFun(){
println("我是public方法")
}

fun test(){
//都可以访问到
publicFun()
protectedFun()
internalFun()
privateFun()
println(num)
}
}

1
2
3
4
5
6
7
8
9
10
package kt

class Layout: View(){
fun test2(){
//在子类中private是访问不到的
publicFun()
protectedFun()
internalFun()
}
}
1
2
3
4
5
6
7
8
9
10
11
package kt

class Main{
fun test(){
val view = View()

//只能访问到public和internal方法
view.publicFun()
view.internalFun()
}
}

我们在前面的文章中也说到了顶层函数和属性。与Java中有所差异的是,private修饰符不光可以用来修饰类与方法和属性,还可以修饰顶层函数和属性。一旦顶层函数和属性被private修饰,那么这些声明就只会在声明它的文件中可见。

当然我们前面也说过扩展函数,这里有一点要注意的是,扩展函数不可以访问到类中被privateprotected修饰的成员。如下代码所示。

Kotlin代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package kt

class Layout: View(){
fun test2(){
//在子类中private是访问不到的
publicFun()
protectedFun()
internalFun()
}
}

fun Layout.getInfo(){
println("我是扩展函数")
publicFun()
internalFun()
//扩展函数不能访问到protected和private的成员方法
}

可见性修饰符总结对比

下面通过表格来对比一下这几种可见性修饰符

修饰符 类成员 顶层声明
public(默认) 所有地方可见 所有地方可见
internal 模块中可见 模块中可见
protected 子类中可见 /
private 类中可见 文件中可见

Kotlin的声明在Java中的处理

由于Kotlin是可以被Java调用的,那我们就需要知道Kotlin代码在被编译为字节码被Java调用时,这些访问控制是怎么被处理的。

1 . privateprotectedpublic会被保留,使用方式与Java中相同

2 . internal在字节码中被处理为public
所以为了保持Kotlin与Java良好的互操作性,当我们用Java访问Kotlin时,一些访问控制和封装性似乎被破坏了。

写在最后

可以看到Kotlin借鉴了Java访问控制符的做法,但同时也完善了自己的一些访问控制,以便于提供更好的封装性,来获得更加优雅安全的代码。

如果博客对您有帮助,不妨请我喝杯咖啡...