The body of a super class is always executed before the body of a sub class. In your case A
calls stringMethod
or intMethod
first, then finally B
's body is executed, assign null
to s
. If you remove that assignment, it should work:
abstract class A{
def this(obj:Object){
this()
obj match{
case s:String => stringMethod(s)
case n:Int => intMethod(n)
}
}
def stringMethod(s:String)
def intMethod(n:Int)
}
class B(obj:Object) extends A(obj){
var s:String = _ // !
def stringMethod(s:String){
this.s = s
}
def intMethod(n:Int){
this.s = n.toString
}
}
val b = new B("foo")
b.s
Neverless, the style is problematic. Here are two alternatives:
trait A {
def obj: Any
def s: String
}
class B(val obj: Any) extends A {
val s = obj match {
case i: Int => i.toString
case x: String => x
case x => throw new IllegalArgumentException(x.toString)
}
}
Or better statically checked:
object B {
def apply(i: Int ): B = new B(i, i.toString)
def apply(s: String): B = new B(s, s)
}
class B private(val obj: Any, val s: String) extends A
B(1.0) // not allowed