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

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

这就给了我一个错误

Super 不是一个表达式,它只能用在左边 一个点

为什么我做不到?

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

 constructor(entity: Entity) : this() {
super.fromEntity(entity)
}
78823 次浏览

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

正如文档所说:

在 Kotlin,实现继承遵循以下规则: 如果一个类从它的直接超类继承了同一个成员的许多实现,它必须覆盖这个成员并提供自己的实现(也许使用其中一个继承的实现)。为了表示从中获取继承实现的超类型,我们使用尖括号中的超类型名称的 super 限定,例如 super。

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

了解更多请阅读 压倒一切的规则

您的代码中有几个问题。

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

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()即可。

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

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

您还可以像下面这样将主构造函数移动到类中:

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

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