编程Android开发者

Kotlin中常量和对象的继承是如何工作的? 在继承和编译时实现不可变属性(const val和val)有哪些陷阱?

用 Hintsage AI 助手通过面试

答复。

在Kotlin中,修饰符const val仅用于文件级的编译时常量,或者在对象(object)和伴随对象中声明。 在类内部声明为val的属性成为普通的最终属性,没有静态初始化。 重要的特点是:const val不能被继承,而val可以被重写(如果允许)。

常量(const val)不能是抽象的,因为它们必须在编译时具有值。 普通的val通过开放属性允许在层次结构中实现常量模式,然而在运行时,它们将通过getter可用,这与Java中的编译不同。

示例:

open class Base { open val info: String = "base" } class Child : Base() { override val info = "child" } object Constants { const val APPLICATION_NAME = "MyApp" }

隐患问题。

可以在接口或抽象类中声明const val,然后重写/继承它吗?

带示例的回答:

不可以。 在Kotlin中,不能在接口或抽象类中声明const val——这仅允许在对象(object)和顶层。 没有可供继承的类似static final变量。

interface Foo { // const val X = "constant" // 编译错误:const 'val'仅允许在顶层、对象或伴随对象中 }

因为对主题细节的不了解而导致的真实错误示例。


故事

团队试图通过在多个Android模块中通过继承接口重用字符串常量,将它们声明为const val——结果收到编译错误,并被迫将常量移动到顶层,从而恶化了封装性。


故事

在项目中将所有Java static final字段转换为Kotlin的val字段在开放类中,期望相同的行为(编译时常量),但它们成为了普通的属性,有getter。 结果,访问时间增加,这对微服务应用程序的热路径产生了负面影响。


故事

在将Java的常量容器类迁移到Kotlin时,开发人员在伴随对象中创建了常量,但在Java代码中遇到了访问问题:常量被视为伴随对象本身的字段,而不是类的字段,这导致API混淆和额外的互操作性错误。