【问题标题】:Data class constructor with two different constructor in KotlinKotlin中具有两个不同构造函数的数据类构造函数
【发布时间】:2017-08-24 21:24:56
【问题描述】:

我是 Kotlin 的新手。我想写一个保存数据的类。我想要两个构造函数。我想要的是这样的

 class InstituteSearchDetails (var centerId: String) {


lateinit var centerId: String;
lateinit var instituteName: String;
lateinit var city: String;

init {
    this.centerId=centerId
}
constructor( instituteName: String, city: String)
{
    this.instituteName=instituteName;
    this.city=city;

}
}

但是在辅助构造函数行它说需要调用主构造函数。我知道需要一些委托,在那里调用主构造函数。我不能从这里调用主构造函数。如果我犯了一些愚蠢的错误,我很抱歉。我对这个东西很陌生

【问题讨论】:

    标签: kotlin


    【解决方案1】:

    来自doc

    如果类有一个主构造函数,每个次构造函数 需要直接或直接委托给主构造函数 间接通过另一个辅助构造函数。委托给 同一类的另一个构造函数是使用 this 关键字完成的:

    例子:

    class Person(val name: String) {
        constructor(name: String, parent: Person) : this(name) {
            parent.children.add(this)
        }
    }
    

    您的代码:

    constructor( instituteName: String, city: String) : this("centerId"){
        this.instituteName=instituteName;
        this.city=city;
    
    }
    

    但看起来您在辅助构造函数中没有 centerId 值。

    你可以有两个辅助构造函数:

    class InstituteSearchDetails {
    
        lateinit var centerId: String;
        lateinit var instituteName: String;
        lateinit var city: String;
    
        constructor(centerId: String) {
            this.centerId = centerId
        }
    
        constructor( instituteName: String, city: String)
        {
            this.instituteName=instituteName;
            this.city=city;
        }
    }
    

    但请注意,例如,如果您使用第二个构造函数,centerId 将不会被初始化,并且如果您在这种情况下尝试访问 centerId,则会收到异常 (UninitializedPropertyAccessException)。

    编辑:

    这在数据类中是不可能的,因为数据类需要具有至少一个 val 或 var 的主构造函数。如果你有主构造函数,那么你的辅助构造函数也应该委托给主构造函数。也许您可以在数据类的单个主构造函数中拥有所有属性,但具有可为空的属性。或查看Sealed class

    sealed class InstituteSearchDetails {
    
        data class InstituteWithCenterId(val centerId: String): InstituteSearchDetails()
        data class InstituteWithNameAndCity(val name: String, val city: String): InstituteSearchDetails()
    
    }
    
    fun handleInstitute(instituteSearchDetails: InstituteSearchDetails) {
    
        when (instituteSearchDetails) {
            is InstituteSearchDetails.InstituteWithCenterId -> println(instituteSearchDetails.centerId)
            is InstituteSearchDetails.InstituteWithNameAndCity -> println(instituteSearchDetails.name)
        }
    
    }
    

    【讨论】:

    • 是的,我在辅助构造函数中没有 centerId 值。这就是问题所在。
    • 我可以对数据类做同样的事情吗?
    • 我不这么认为。数据类需要具有至少一个 val 或 var 的主构造函数。如果你有主构造函数,你的辅助构造函数也应该委托给主构造函数。也许您可以在一个主构造函数中拥有所有属性,但具有可为空的属性。
    • 或者你可以考虑sealed class。检查此answerdoc
    • 我也用密封类更新了答案,您可以在其中使用数据类并避免可为空的属性。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-19
    • 2023-04-03
    相关资源
    最近更新 更多