Kotlin 父类的init块中的null值

Kotlin 父类的init块中的null值,kotlin,Kotlin,我正在创建一个非常简单的kotlin程序,看到父类有一个奇怪的行为 代码是: fun makeSalt(name:String) = Spice(name, "non-spicy") fun main(args: Array<String>) { var salt : Spice = Spice("salt", "non-spicy") println("Salt heat = ${salt.heat}") val spicelist = listOf&l

我正在创建一个非常简单的kotlin程序,看到父类有一个奇怪的行为

代码是:

fun makeSalt(name:String) = Spice(name, "non-spicy")
fun main(args: Array<String>) {
    var salt : Spice = Spice("salt", "non-spicy")

    println("Salt heat = ${salt.heat}")

    val spicelist = listOf<Spice>(
        Spice("salt", "non-spicy"),
        Spice("turmeric", "mild"),
        Spice("Pepper", "hot"),
        Spice("Chilli", "hot"),
        Spice("Sugar", "non-spicy")
    )

    val mildSpices = spicelist.filter{it.heat <=5}

    val salt2 = makeSalt("rock salt")

    val bhoot : SubSpice = SubSpice("bhoot", "hot")
}


open class Spice(open var name:String, open var spiciness:String = "mild" ){
    var heat : Int = 5
        get() = when (spiciness){
            "mild"->5
            "hot"->10
            "non-spicy"->1
            else -> 0

        }

    init{
        if(spiciness === null) {println("spiciness is null")}
        else println("Spiciness of ${name} = ${spiciness}; heat = ${heat}")
    }
}

class SubSpice(override var name:String, override var spiciness:String = "hot") : Spice(name, spiciness){

}

如您所见,当我创建子类的对象时,父类的变量
spiciness
变为null。有人能解释为什么会这样吗?我希望它为null,因为它还有默认参数
“mild”

当您不重写任何getter/setter方法时,您正在使用
openvar

您引入了奇怪的初始化冲突,因为
Spice.init
(父类构造函数)在
子空间.init
之前被调用,并且通过重写字段,它们不再与父构造函数一起初始化-相反,一旦构建了
子空间
,它们将可用


从父类中的变量中删除
open
关键字,并在子构造函数中删除
override var
,这样,字段将在
Spice
类中正确初始化,其
init
块将成功运行。

当您不重写任何getter/setter方法时,您正在使用
openvar

您引入了奇怪的初始化冲突,因为
Spice.init
(父类构造函数)在
子空间.init
之前被调用,并且通过重写字段,它们不再与父构造函数一起初始化-相反,一旦构建了
子空间
,它们将可用


从父类中的变量中删除
open
关键字,并在子构造函数中重写var,这样,字段将在
Spice
类中正确初始化,其
init
块将成功运行。

要为Pawel的答案添加额外信息:

如果使用
open
重写属性,则基类中的init块将在初始化派生属性之前运行

见文件:

因此,如果我们像Pawel建议的那样更改代码,我们将得到如下结果:

fun main(args: Array<String>) {
    Spice("salt", "non-spicy")
    Spice(name="spice")
    SubSpice(name = "bhoot", spiciness = "hot")
    SubSpice(name="subspice")
}

open class Spice(var name:String, var spiciness : String = "mild" ) {
    var heat : Int = 5
        get() = when (spiciness){
            "mild"->5
            "hot"->10
            "non-spicy"->1
            else -> 0
        }

    init{
        if(spiciness === null) {println("spiciness is null")}
        else println("Spiciness of ${name} = ${spiciness}; heat = ${heat}")
    }
}

class SubSpice(name: String, spiciness : String = "hot") : Spice(name, spiciness) {
}

要在Pawel的回答中添加额外信息:

如果使用
open
重写属性,则基类中的init块将在初始化派生属性之前运行

见文件:

因此,如果我们像Pawel建议的那样更改代码,我们将得到如下结果:

fun main(args: Array<String>) {
    Spice("salt", "non-spicy")
    Spice(name="spice")
    SubSpice(name = "bhoot", spiciness = "hot")
    SubSpice(name="subspice")
}

open class Spice(var name:String, var spiciness : String = "mild" ) {
    var heat : Int = 5
        get() = when (spiciness){
            "mild"->5
            "hot"->10
            "non-spicy"->1
            else -> 0
        }

    init{
        if(spiciness === null) {println("spiciness is null")}
        else println("Spiciness of ${name} = ${spiciness}; heat = ${heat}")
    }
}

class SubSpice(name: String, spiciness : String = "hot") : Spice(name, spiciness) {
}

谢谢由于我不能将你们的两个答案都标为“已接受”,我已将波维尔的答案标为“已接受的一方”。由于我不能将你们的两个答案都标为“已接受”,所以我将Pawel的答案标为“已接受”
Spiciness of salt = non-spicy; heat = 1
Spiciness of spice = mild; heat = 5
Spiciness of bhoot = hot; heat = 10
Spiciness of subspice = hot; heat = 10