所以我今天開始學習 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) {}
init 方法將列印出:(Ani init) New animal: Dog called null with 0 speed.
起初我以為我在某個地方搞砸了,不知何故我沒有將引數正確地傳遞給Animal類,但后來我添加了這兩行代碼:
init {
println("(Dog init) New animal: $type called $name with $speed speed")
}
Dog上課,和
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后照常訪問它們?Dog
uj5u.com熱心網友回復:
您應該收到編譯器警告。你不應該open在構造時使用屬性或函式(在init塊或屬性宣告中),因為它會導致這種不需要的行為。這幾乎是在 Kotlin 中不使用!!.
它發生的原因是超類的建構式(包括init塊和屬性宣告)在子類之前運行。由于您在子類中覆寫了該屬性,因此在呼叫超類時name該屬性的支持欄位name尚未初始化init,因此該屬性回傳默認的 Java 欄位值null。在 的情況下speed,欄位型別是 Java 原語int,因此其默認值為 0。
請注意,在您的特定示例中,無需覆寫這些屬性,因為無論如何您都將這些值傳遞給超級建構式。您可以洗掉open屬性之前的關鍵字并宣告您的 Dog 如下:
class Dog(
name: String,
speed: Int,
): Animal("Dog", name, speed) {}
然后它將正常運行。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/428623.html
上一篇:LNK2019:未決議的外部符號-在VisualStudio2022中將.h檔案與.cpp(定義)檔案鏈接不起作用
