问题
I have abstract class A
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)
}
and I have a class that extends this class
class B(obj:Object) extends A(obj){
var s:String = null
def stringMethod(s:String){
this.s = s
}
def intMethod(n:Int){
this.s = n.toString
}
}
The point of this class is to instantiate an object and its variables depending on the class type of the object used to instantiate it but the problem is that when the abstract constructor is called, the default constructor of object which is extending the abstract object is somehow being called after. This alters the value of var s back to null.
This a really simple implementation of my classes and I have more variables in class B and more logic inside intMethod and stringMethod.
I realize this might be a completely wrong way of doing this, so if there is a better way please let me know.
回答1:
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
来源:https://stackoverflow.com/questions/22363381/how-to-extend-an-abstract-class-in-scala-and-use-the-abstract-constructor