Reputation: 4358
I have two classes Entity
and Account
as
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;
}
}
and
data class Account(
var name: String? = null,
var accountFlags: Int? = null
) : Entity() {
constructor(entity: Entity) : this() {
super(entity)
}
}
Which gives me the error
Super is not an expression, it can be only used in the left-hand side of a dot '.'
Why cannot I do that?
The following will pass the compilation error, but I am not sure if it is correct.
constructor(entity: Entity) : this() {
super.fromEntity(entity)
}
Upvotes: 93
Views: 103771
Reputation: 43821
You have a couple of problems in your code.
First, this is the correct syntax to call a super constructor from a secondary constructor:
constructor(entity: Entity) : super(entity)
Second, you can't call a super constructor from a secondary constructor if your class has a primary constructor (which your class does).
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)
}
Here, the copy constructor is in the child class which just delegates to the primary constructor.
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
}
}
Here I'm only using secondary constructors in the child class, which lets me delegate them to individual super constructors. Notice how the code is pretty long.
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()
Here I omitted the copy constructors and made the properties abstract, so the child class has all the properties. I also made the child class a data class
. If you need to clone the class, you can simply call account.copy()
.
Upvotes: 126
Reputation: 5073
That's what I was looking for, no modifier or val/var on argument to have it used for parent(super) call
open class Dad(protected val name: String){
}
open class Son(protected val nickname: String, name: String): Dad(name){
...
}
Upvotes: 0
Reputation: 303
You can also move your primary constructor down into the class like this:
data class Account: Entity {
constructor(): super()
constructor(var name: String? = null, var accountFlags: Int? = null): super()
constructor(entity: Entity) : super(entity)
}
Advantage of this is, compiler will not require your secondary constructor to call primary constructor.
Upvotes: 17
Reputation: 1954
Another option is to create companion object and provide factory method e.g.
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)
}
}
}
Upvotes: 3
Reputation: 17809
Use this super<Entity>.fromEntity(entity)
to call super class methods.
As Documentation says:
In Kotlin, implementation inheritance is regulated by the following rule: if a class inherits many implementations of the same member from its immediate superclasses, it must override this member and provide its own implementation (perhaps, using one of the inherited ones). To denote the supertype from which the inherited implementation is taken, we use super qualified by the supertype name in angle brackets, e.g. super.
constructor(entity: Entity) : this() {
super<Entity>.fromEntity(entity)
}
To know more read Overriding Rules
Upvotes: 1