How does constructor delegation work with pure constructors?
← Constructor Delegation · Ref: Q586
Pure constructors can use both this() and super() delegation, following the same first-statement rule. The key requirement is that ALL constructors must be consistently pure (E05190).
PURE THIS() DELEGATION
Pure constructors can delegate to another pure constructor with this():
Config() as pure -> host as String this(host, 8080) Config() as pure -> host as String, port as Integer this.host :=? host this.port :=? port
PURE SUPER() DELEGATION
Pure child constructors can call pure parent constructors with super():
Child() as pure -> name as String, extra as Integer super(name) this.extra :=? extra
CONSISTENCY REQUIREMENT
If the parent has pure constructors, and you extend it, your constructors must also be pure. If the parent has non-pure constructors, your constructors must also be non-pure.
GUARDED ASSIGNMENT
Pure constructors use ':=?' for field assignment after delegation. The delegated constructor may have already set some fields.
See Q563 for pure constructor basics. See Q564 for all-or-nothing purity. See Q565 for multiple pure constructors. See Q580 for this() delegation.
Example
defines module qa.constructor.puredelegation defines class //Parent with pure constructors Coordinates as open latitude as Float: Float() longitude as Float: Float() Coordinates() as pure -> latitude as Float longitude as Float this.latitude :=? latitude this.longitude :=? longitude latitude() as pure <- rtn as Float: latitude longitude() as pure <- rtn as Float: longitude default operator ? //Child: pure constructors with both this() and super() Location extends Coordinates locationName <- String() //this() delegation in pure constructor Location() as pure -> locationName as String this(locationName, 0.0, 0.0) //super() delegation in pure constructor Location() as pure -> locationName as String latitude as Float longitude as Float super(latitude, longitude) this.locationName :=? locationName locationName() as pure <- rtn as String: locationName default operator ? defines program PureConstructorDelegationDemo() stdout <- Stdout() //this() delegation path loc1 <- Location("Unknown") stdout.println(`${loc1.locationName()}: (${loc1.latitude()}, ${loc1.longitude()})`) //super() delegation path loc2 <- Location("London", 51.5074, -0.1278) stdout.println(`${loc2.locationName()}: (${loc2.latitude()}, ${loc2.longitude()})`)
Common mistakes
E05190 — If any constructor is pure, ALL constructors must be pure. Mixing pure and non-pure constructors in the same class is invalid. See ek9 -h E05190 for details.
Incorrect:
Location()
-> locationName as String
this(locationName, 0.0, 0.0)
Correct:
Location() as pure -> locationName as String this(locationName, 0.0, 0.0)
E05050 — Even in pure constructors, super() must be the first statement. No field assignments can precede the parent delegation. See ek9 -h E05050 for details.
Incorrect:
Location() as pure -> locationName as String latitude as Float longitude as Float this.locationName :=? locationName super(latitude, longitude)
Correct:
Location() as pure -> locationName as String latitude as Float longitude as Float super(latitude, longitude) this.locationName :=? locationName
Other ways to ask this
- Can pure constructors use this() and super()?
- How do I chain pure constructors with delegation?
- What are the rules for pure constructor delegation?
Coming from another language?
Java: no pure constructor concept. Kotlin: no constructor purity. EK9: pure constructors support this() and super() delegation, all constructors must be consistently pure (E05190), :=? for field assignment.
Keywords: super, pure, constructor, E05190, side-effect, chain, guarded, null-safe, constant, immutable, delegation, this, safe, isset