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

时间:2017-06-11 07:10:15

标签: kotlin

我有两个班级EntityAccount

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;
    }
}

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

    constructor(entity: Entity) : this() {
        super(entity)
    }
}

这给了我错误

  

超级不是表达式,它只能用在左侧   一个点'。'

为什么我不能这样做?

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

 constructor(entity: Entity) : this() {
    super.fromEntity(entity)
}

4 个答案:

答案 0 :(得分:45)

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

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

constructor(entity: Entity) : super(entity)

其次,如果您的类具有主要构造函数(您的类所做的那样),则无法从辅助构造函数调用超级构造函数。

解决方案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)
}

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

解决方案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
    }
}

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

解决方案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()

这里我省略了复制构造函数并使属性成为抽象,因此子类具有所有属性。我还让孩子成为data class。如果您需要克隆课程,只需拨打account.copy()

即可

答案 1 :(得分:2)

您还可以像下面这样将您的主要构造函数移至该类中:

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

此方法的优点是,编译器不需要您的辅助构造函数调用主构造函数。

答案 2 :(得分:0)

使用此super<Entity>.fromEntity(entity)来调用超类方法。

正如文档所说:

  

在Kotlin中,实现继承受以下规则的约束:如果一个类从其直接超类继承同一成员的许多实现,它必须覆盖此成员并提供其自己的实现(可能使用其中一个继承的实现) 。为了表示从中进行继承实现的超类型,我们在尖括号中使用超类型名称的超限定,例如超级。

constructor(entity: Entity) : this() {
    super<Entity>.fromEntity(entity)
}

了解更多阅读Overriding Rules

答案 3 :(得分:0)

另一种选择是创建伴随对象并提供工厂方法,例如

class Account constructor(
        var name: String? = null,
        var accountFlags: Int? = null,
        id: String?,
        created: Date?
) : Entity(id, created) {

    companion object {
        fun fromEntity(entity: Entity): Account {
            return Account(null, null, entity.id, entity.created)
        }
    }
}