Kotlin: How can a child constructor use its parent

2019-05-03 09:02发布

问题:

For example, we have this parent:

open class Parent(val id: Int, val name: String?) {
    constructor() : this(-1, null)
}

And a child, which must have both a two-param constructor and an empty constructor, like the parent:

class Child(id: Int, name: String?) : Parent(id, name) {
    constructor() : super() // syntax error
}

How can a child constructor use its parent's secondary constructor?

I am aware that I can implement a child constructor passing in the same values as the parent, but this not only seems redundant but also often times my childs have extra parameters for its primary constructor, but don't require intermediary constructors (constructors with params that don't include all the extra params). Here's an example child implementing it that way, in case I wasn't clear:

class Child(id: Int, name: String?) : Parent(id, name) {
    constructor() : this(-1, null) // no syntax error, but redundant
}

回答1:

The best way to achieve this is imho using default parameters for your constructor

class Child(id: Int = -1, name: String? = null) : Parent(id, name)

Depending on how much influence you've got on the Parent class, maybe even

class Parent(val id: Int = -1, val name: String? = null)

This has one "drawback", though: you'll technically get three different constructors. But I can't see how this could be a problem, since you have to handle the id=-1 and name=null cases anyway.

Additionally, I don't think your solution

class Child(id: Int, name: String?) : Parent(id, name) {
    constructor() : this(-1, null) 
}

is bad, or "redundant" in any way - on the contrary: it's highly expressive and explicit, so the reader knows exactly what your intention was.



回答2:

First, you can't extends the Parent class since it is not opened.

Secondly, if a class has declared a primary constructor, you can't call the constructor of the superclass via super keyword.

On the other hand, if you want to call the superlcass's constructor by the keyword super. you need make the primary constructor to the secondary constructor, for example:

class Child : Parent {
  constructor(id: Int, name: String?) : super(id, name)
  constructor() : super()
}

Another option is let the secondary constructor call the primary constructor by this keyword, but I think it is unnecessary and duplicated parameters with superclass's secondary constructor:

class Child(id: Int, name: String?) : Parent(id, name) {
  constructor() : this(-1, null);
}