在Kotlin中调用超类构造函数,Super不是表达式

Amr*_*awy 29 kotlin

我有两个班Entity,并Account

abstract class Entity(
    var id: String? = null,
    var created: Date? = Date()) {

    constructor(entity: Entity?) : this() {
        fromEntity(entity)
    }

    fun fromEntity(entity: Entity?): Entity {
        id = entity?.id
        created = entity?.created
        return this;
    }
}
Run Code Online (Sandbox Code Playgroud)

data class Account( 
    var name: String? = null,
    var accountFlags: Int? = null
) : Entity() {

    constructor(entity: Entity) : this() {
        super(entity)
    }
}
Run Code Online (Sandbox Code Playgroud)

这给了我错误

超级不是表达式,它只能用在点'左'的左侧.

为什么我不能这样做?

以下将传递编译错误,但我不确定它是否正确.

 constructor(entity: Entity) : this() {
    super.fromEntity(entity)
}
Run Code Online (Sandbox Code Playgroud)

Kir*_*man 64

您的代码中存在一些问题.

首先,这是从辅助构造函数调用超级构造函数的正确语法:

constructor(entity: Entity) : super(entity)
Run Code Online (Sandbox Code Playgroud)

其次,如果您的类具有主构造函数(您的类具有),则无法从辅助构造函数调用超级构造函数.

解决方案1

abstract class Entity(
        var id: String,
        var created: Date
)

class Account(
        var name: String,
        var accountFlags: Int,
        id: String,
        created: Date
) : Entity(id, created) {
    constructor(account: Account) : this(account.name, account.accountFlags, account.id, account.created)
}
Run Code Online (Sandbox Code Playgroud)

这里,复制构造函数位于子类中,它只委托给主构造函数.

解决方案2

abstract class Entity(
        var id: String,
        var created: Date
) {
    constructor(entity: Entity) : this(entity.id, entity.created)
}

class Account : Entity {
    var name: String
    var accountFlags: Int

    constructor(name: String, accountFlags: Int, id: String, created: Date) : super(id, created) {
        this.name = name
        this.accountFlags = accountFlags
    }

    constructor(account: Account) : super(account) {
        this.name = account.name
        this.accountFlags = account.accountFlags
    }
}
Run Code Online (Sandbox Code Playgroud)

这里我只在子类中使用辅助构造函数,它允许我将它们委托给单独的超级构造函数.注意代码是如何很长的.

解决方案3(最惯用的)

abstract class Entity {
    abstract var id: String
    abstract var created: Date
}

data class Account(
        var name: String,
        var accountFlags: Int,
        override var id: String,
        override var created: Date
) : Entity()
Run Code Online (Sandbox Code Playgroud)

在这里,我省略了复制构造函数并使属性成为抽象,因此子类具有所有属性.我也让孩子上课了data class.如果你需要克隆类,你可以简单地调用account.copy().

  • 谢谢。我已经尝试过语法 `constructor(entity: Entity) : super(entity)` 但它给出了相同的错误 `super 不是表达式...` 我没有尝试您建议的代码,但我有一个担心。如果我必须在每个孩子中再次定义相同的字段,那么拥有父母有什么好处? (2认同)

Jef*_*eff 8

您还可以将主构造函数向下移动到类中,如下所示:

data class Account: Entity {
    constructor(): super()
    constructor(var name: String? = null, var accountFlags: Int? = null): super()
    constructor(entity: Entity) : super(entity)
}
Run Code Online (Sandbox Code Playgroud)

这样做的好处是,编译器不需要你的辅助构造函数来调用主构造函数。