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

qqrboqgw  于 2023-04-07  发布在  Kotlin
关注(0)|答案(5)|浏览(182)

我有两个类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)
}
myss37ts

myss37ts1#

你的代码中有几个问题。
首先,这是从二级构造函数调用超级构造函数的正确语法:

constructor(entity: Entity) : super(entity)

其次,如果你的类有一个主构造函数(你的类有),你就不能从构造函数调用超级构造函数。

方案一

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

在这里,复制构造函数在子类中,子类只是委托给主构造函数。

方案二

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

这里我只在子类中使用了二级构造函数,这样我就可以把它们委托给单独的超级构造函数。

方案三(最惯用)

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()

tktrz96b

tktrz96b2#

你也可以像这样把你的主构造函数移到类中:

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

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

gpfsuwkq

gpfsuwkq3#

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

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)
        }
    }
}
guz6ccqo

guz6ccqo4#

使用super<Entity>.fromEntity(entity)调用超类方法。
正如文档所说:
在Kotlin中,实现继承由以下规则管理:如果一个类从它的直接超类继承了同一个成员的许多实现,它必须覆盖这个成员并提供它自己的实现(也许,使用继承的实现之一)。为了表示继承实现所取的超类型,我们使用超类型,由尖括号中的超类型名称限定,例如super。

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

要了解更多信息,请阅读覆盖规则

owfi6suc

owfi6suc5#

这就是我所寻找的,没有修饰符或瓦尔/var的参数,使它用于父(超)调用

open class Dad(protected val name: String){
}

open class Son(protected val nickname: String, name: String): Dad(name){
...
}

相关问题