Kotlin - Class 继承;覆盖属性
Kotlin - Class Inheritance; Overriding properties
所以我今天开始学习 Kotlin,当我发现一些奇怪的东西时就开始 类。
当我 运行 此代码时:
fun main() {
val dog_1 = Dog("Walrek", 7)
}
open class Animal(
open val type: String,
open val name: String,
open val speed: Int,
) {
init {
println("(Ani init) New animal: $type called $name with $speed speed")
}
}
class Dog(
override val name: String,
override val speed: Int,
): Animal("Dog", name, speed) {}
初始化方法会打印出:(Ani init) New animal: Dog called null with 0 speed
.
起初我以为我搞砸了某个地方,不知何故我没有将参数正确传递到 Animal
class,但后来我添加了这两行代码:
init {
println("(Dog init) New animal: $type called $name with $speed speed")
}
变成Dog
class,然后
println(dog_1.name)
在 main
函数中,并将其作为输出:
(Ani init) New animal: Dog called null with 0 speed
(Dog init) New animal: Dog called Walrek with 7 speed
Walrek
所以现在我的问题是,为什么参数没有传递到 Animal
class,但我可以在创建 Dog
实例后照常访问它们?
您应该收到编译器警告。你不应该在构造时使用 open
属性或函数(在 init
块或 属性 声明中),因为它会导致这种不需要的行为。这是在不使用 !!
.
的情况下在 Kotlin 中获得 NullPointerException 的唯一方法
发生这种情况的原因是超类的构造函数(包括 init
块和 属性 声明)在子类之前 运行。由于您在子类中覆盖了 属性 name
,因此 属性 name
的支持字段在超类的 init
时尚未初始化调用,所以 属性 returns 的默认 Java 字段值为 null
。在 speed
的情况下,字段类型是 Java 原语 int
所以它的默认值为 0.
请注意,在您的特定示例中,没有必要覆盖这些属性,因为您无论如何都将这些值传递给超构造函数。您可以删除属性前的 open
关键字并声明您的狗:
class Dog(
name: String,
speed: Int,
): Animal("Dog", name, speed) {}
然后它将正常运行。
所以我今天开始学习 Kotlin,当我发现一些奇怪的东西时就开始 类。 当我 运行 此代码时:
fun main() {
val dog_1 = Dog("Walrek", 7)
}
open class Animal(
open val type: String,
open val name: String,
open val speed: Int,
) {
init {
println("(Ani init) New animal: $type called $name with $speed speed")
}
}
class Dog(
override val name: String,
override val speed: Int,
): Animal("Dog", name, speed) {}
初始化方法会打印出:(Ani init) New animal: Dog called null with 0 speed
.
起初我以为我搞砸了某个地方,不知何故我没有将参数正确传递到 Animal
class,但后来我添加了这两行代码:
init {
println("(Dog init) New animal: $type called $name with $speed speed")
}
变成Dog
class,然后
println(dog_1.name)
在 main
函数中,并将其作为输出:
(Ani init) New animal: Dog called null with 0 speed
(Dog init) New animal: Dog called Walrek with 7 speed
Walrek
所以现在我的问题是,为什么参数没有传递到 Animal
class,但我可以在创建 Dog
实例后照常访问它们?
您应该收到编译器警告。你不应该在构造时使用 open
属性或函数(在 init
块或 属性 声明中),因为它会导致这种不需要的行为。这是在不使用 !!
.
发生这种情况的原因是超类的构造函数(包括 init
块和 属性 声明)在子类之前 运行。由于您在子类中覆盖了 属性 name
,因此 属性 name
的支持字段在超类的 init
时尚未初始化调用,所以 属性 returns 的默认 Java 字段值为 null
。在 speed
的情况下,字段类型是 Java 原语 int
所以它的默认值为 0.
请注意,在您的特定示例中,没有必要覆盖这些属性,因为您无论如何都将这些值传递给超构造函数。您可以删除属性前的 open
关键字并声明您的狗:
class Dog(
name: String,
speed: Int,
): Animal("Dog", name, speed) {}
然后它将正常运行。