How to call super constructor, when the super class has a it-block constructor. Thanks.
new make(|This| f) : super.make(null) { f(this) } //throw FieldNotSetErr
new make2(|This| f) : super.make(f) {} //Sub class is not inited correctly
Test code:
const class Val {
const Int v
new make(Int val) { v = val }
override Str toStr() { v.toStr }
}
class Base {
Val a
new make(|This|? f := null) {
f?.call(this)
}
}
class Sub : Base {
Val b := Val(-1)
new make(|This| f) : super.make(null) {
f(this)
}
new make2(|This| f) : super.make(f) {
}
}
class Main {
static Void main() {
//echo("Hello World")
x := Sub.make2 {
a = Val(1)
b = Val(2)
echo("init")
}
echo("$x.a, $x.b")
}
}
SlimerDudeThu 24 Nov 2016
Hi Go4, that's a good tricky question!
Using new make(|This| f) : super.make(f) {} is the way to chain it-block ctors, only it doesn't work in your example!
Here's the sequence of events that explains why it doesn't work:
You call Sub.make2()
Base is created
Default values for fields in Base are set. (Which in your example, there aren't any)
The Base ctor is called, which sets a and b
Sub is created
Default values for fields in Sub are set. ( Note field b is now overridden with the default value of -1 )
The Sub ctor is called
As noted, this is not very ideal; perhaps Brian can ticket a better way to initialise classes / ctors?
Following is a workaround, essentially you move setting the default values to the ctor, checking first if it's been set.
class Base {
Str a
new make(|This| f) { f(this) }
}
class Sub : Base {
Str b
new make(|This| f) : super.make(f) {
// thankfully this still compiles in the ctor despite b not being nullable
if (b == null)
b = "-1"
}
}
...
x1 := Sub { it.a = "1" }
echo("$x1.a, $x1.b") // --> 1, -1
x2 := Sub {
it.a = "1"
it.b = "2"
}
echo("$x2.a, $x2.b") // --> 1, 2
go4Fri 25 Nov 2016
Thank you, it's good idea to set the default values in ctor.
go4 Thu 24 Nov 2016
How to call super constructor, when the super class has a it-block constructor. Thanks.
new make(|This| f) : super.make(null) { f(this) } //throw FieldNotSetErr new make2(|This| f) : super.make(f) {} //Sub class is not inited correctlyTest code:
const class Val { const Int v new make(Int val) { v = val } override Str toStr() { v.toStr } } class Base { Val a new make(|This|? f := null) { f?.call(this) } } class Sub : Base { Val b := Val(-1) new make(|This| f) : super.make(null) { f(this) } new make2(|This| f) : super.make(f) { } } class Main { static Void main() { //echo("Hello World") x := Sub.make2 { a = Val(1) b = Val(2) echo("init") } echo("$x.a, $x.b") } }SlimerDude Thu 24 Nov 2016
Hi Go4, that's a good tricky question!
Using
new make(|This| f) : super.make(f) {}is the way to chain it-block ctors, only it doesn't work in your example!Here's the sequence of events that explains why it doesn't work:
Sub.make2()Baseis createdBaseare set. (Which in your example, there aren't any)Basector is called, which setsaandbSubis createdSubare set. ( Note fieldbis now overridden with the default value of-1)Subctor is calledAs noted, this is not very ideal; perhaps Brian can ticket a better way to initialise classes / ctors?
Following is a workaround, essentially you move setting the default values to the ctor, checking first if it's been set.
class Base { Str a new make(|This| f) { f(this) } } class Sub : Base { Str b new make(|This| f) : super.make(f) { // thankfully this still compiles in the ctor despite b not being nullable if (b == null) b = "-1" } } ... x1 := Sub { it.a = "1" } echo("$x1.a, $x1.b") // --> 1, -1 x2 := Sub { it.a = "1" it.b = "2" } echo("$x2.a, $x2.b") // --> 1, 2go4 Fri 25 Nov 2016
Thank you, it's good idea to set the default values in ctor.