Kotlin可见性修饰符

本文探讨了Kotlin与Java中可见性修饰符的区别,包括默认修饰符的不同,Kotlin的internal和private修饰符的独特用法,以及Kotlin中protected修饰符的访问范围。Kotlin强调模块内访问,防止类的不必要暴露,同时允许在文件内声明private类和方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Java为我们提供了public、protected、private以及default四个可见性修饰符,用来指定类、方法及属性的可见性。Kotlin中的可见性修饰符与Java中的很类似,但也有不一样的地方,主要有以下几点:

  • Kotlin与Java的默认修饰符不同,Kotlin中是public,而Java中是default;
  • Kotlin中有一个独特的修饰符internal;
  • Kotlin可以在一个文件内单独声明方法及常量,同样支持可见性修饰符;
  • Java中除了内部类可以用private修饰以外,其他类都不允许private修饰,而Kotlin可以;
  • Kotlin和Java中的protected的访问范围不同,Java中是包、类及子类可访问,而Kotlin只允许类及子类。

默认修饰符

很多时候,我们在实现类或者方法的时候都会省略它的修饰符。当然,在Java中我们很自然地会给类加上public修饰符,因为大多数类都可能需要在全局访问。而Java的默认修饰符是default,它只允许包内访问。虽然通常IDE会自动帮我们加上public修饰符,但是这也让人觉得它是一个多余的声明。所以,出于简洁性的考虑,Kotlin将默认可见修饰符指定为了public。

前面我们说到了Java中默认修饰符是default,它的作用域是包内可访问。那么Kotlin中有类似的修饰符吗?

Kotlin中的作用域

Kotlin中的作用域可以被称作模块内访问。那么什么是模块呢?模块可以看作一起编译的Kotlin文件组成的集合。那么,Kotlin中为什么要定义这种新的作用域呢?难道Java提供的包内访问作用域不香吗?Java的包内访问作用域确实存在一些问题。举个例子:假如我们在Java项目中定义了一个类,使用了默认修饰符,那么这个类是包内可见,其他外部类将无法访问它。接下来我们把这个项目打包成一个类库,并提供给其他的项目使用。这时候,如果开发者想访问之前定义的这个类,除了复制源代码之外,还有一个方式。就是在程序中创建一个包,它的名字与该类所在的包的名字一致。通过这种方式,就可以直接访问我们前面定义的类了。换句话说,我们之前定义的类就被泄露了,这很有可能导致问题。示例代码如下:

package com.dripower

/** 第三方类库代码 */
class TestDefault {
  ...
}
package com.dripower

/** 在我们的项目中创建com.dripower包 */
class Test {
  TestDefault td = new TestDefault()
}

Kotlin并没有采用这种包内可见的作用域,而是使用了模块内可见的作用域。模块内可见指的是该类只对一起编译的其他Kotlin文件可见。由于开发工程与第三方类库不属于同一个模块,因此就解决了Java中存在的问题。这就是Kotlin中internal修饰符的作用。

在Java程序中,我们很少见到用private修饰的类,因为Java中的类或方法没有单独属于某个文件的概念。对于某个文件来说,它里面的类要么是public,要么是包私有,而没有只属于这个文件的概念。若要用private修饰,那么这个只能是其他类的内部类。而Kotlin中则可以用private给单独的类修饰,它的作用域就是当前这个Kotlin文件。比如:

package com.dripower.car

class BMWCar(val name: String) {
  private val bMWEngine = Engine("BMW")

  fun getEngine(): String{
    return bMWEngine.engineType()
  }
}

private class Engine(val type: String) {
  fun engineType(): String {
    return "theenginetypeis$type"
  }
}

Kotlin中的protected修饰符

除了private修饰符的差别,Kotlin中的protected修饰符也与Java有所不同。Java中的protected修饰的内容作用域是包内、类及子类可访问,而在Kotlin中,由于没有包作用域的概念,所以protected修饰符在Kotlin中的作用域只有类及子类。我们对上面的代码稍加修改:

package com.dripower.car

class BMWCar(val name: String) {
  private val bMWEngine = BZEngine("BMW")

  fun getEngine(): String {
    return bMWEngine.engineType() // 编译错误,engineType只对类及子类可见
  }
}

private open class Engine(val type: String) {
  protected open fun engineType(): String {
    return "theenginetypeis$type"
  }
}

private class BZEngine(type:String): Engine(type) {
  override fun engineType(): String {
    return super.engineType()
  }
}

我们可以发现,同一个包下的其他类不能访问protected修饰的内容,而在子类中则可以访问。

总结一下,可见性修饰符在Kotlin与Java中大致相似,但也有自己的很多特殊之处。这些可见性修饰符比较如下所示。

修饰符含义与Java的比较
public(默认)Kotlin中的默认修饰符与Java中的public效果相同
protected类及子类可见含义一致,但作用域除了类及子类之外,包内也可见
private类内修饰只有本类可见,类外修饰文件内可见只有类内可见
internal模块内可见
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值