I asked a question earlier: here and although I accepted the answer I'm still very far from actually understanding, so I dug a bit deeper and I'm writing a further question.
The behaviour of overriding val in scala surprises me. For example, given this code:
class A {
val name = "AAAAA"
}
class B extends A {
override val name = "BBBBB"
}
if I say:
object Atest extends App {
val b = new B
println(b.name)
val a = b.asInstanceOf[A]
println(a.name)
}
I expect
BBBBB
AAAAA
but I get
BBBBB
BBBBB
I'm just trying to see the AAAAA value that I think A should be storing somewhere. So I try:
class A {
val name = "AAAAA"
def showSuper {
println(name)
}
}
and:
val b = new B
val a = b.asInstanceOf[A]
b.showSuper
a.showSuper
but I still get:
BBBBB
BBBBB
So I try do have a look at what scala is actually generating from my classes:
scalac -Xprint:all A.scala
gives me
class A extends Object {
private[this] val name: String = _;
<stable> <accessor> def name(): String = A.this.name;
def <init>(): p3.A = {
A.super.<init>();
A.this.name = "AAAAA";
()
}
};
class B extends p3.A {
private[this] val name: String = _;
override <stable> <accessor> def name(): String = B.this.name;
def <init>(): p3.B = {
B.super.<init>();
B.this.name = "BBBBB";
()
}
}
The call to B.super happens before B.this.name even gets set and A clearly sets its name to AAAAA.
What is going on? Why, when I override a val like this, can I not see A's value (or is it getting set to B's value?) What is the mechanism by which this happens? How can I see this mechanism - is there a piece of scala source code that shows me why this happens?
Many thanks
EDIT: Meant to add that if I use javap to look at the bytecode, it clearly shows that A and B each have their own copy of the name variable:
$ javap -private A
Compiled from "A.scala"
public class p3.A extends java.lang.Object{
private final java.lang.String name;
public java.lang.String name();
public p3.A();
}
$ javap -private B
Compiled from "A.scala"
public class p3.B extends p3.A{
private final java.lang.String name;
public java.lang.String name();
public p3.B();
}
So it's not like A and B have to be sharing the same variable - they each have the potential for using their own copy.