-
-
Save ogirardot/4683919 to your computer and use it in GitHub Desktop.
object MyApp extends App { | |
val b = new B() | |
} | |
trait Conflictor { | |
val log = "reduction" | |
} | |
class A {} | |
object A extends Conflictor {} | |
class B extends A with Conflictor {} |
I get a VerifyError at runtime: class B overrides final method log.()Ljava/lang/String;
Interesting..
Btw : It fails in scala 2.9.2, it works in scala 2.10.0. Interesting.
Apparently, in Scala 2.9.2, A
makes log
final. See javap for A
:
public class A extends java.lang.Object implements scala.ScalaObject{
public static final void Conflictor$_setter_$log_$eq(java.lang.String);
public static final java.lang.String log();
public A();
}
Hence the problem for B
.
This is an answer, but it may not be right :)
The object A is instantiated where defined. So it defines a val log on itself.
If I remember well, Scala compiles object A so that java code can call A.log (as a static value), so there should be a "log" member in class A calling log in A$ (am I right?)
So this could explain why B cannot extend A with Conflictor, because it tries to 'define' log a second time (there's already one in A)
yes but :
case class ahoy(s:String) {def apply(s:String) = ahoy(s + this.s)}
ahoy("a")("b") == ahoy("ba")
works fine. (there are a lot more collisions here)
So my idea is the compiler is avoiding collision in A
, but place unsafe static accessor for log if it can.
This one works :
object MyApp extends App {
val b = new B()
}
trait Conflictor {
val log = "reduction"
}
class A extends Conflictor {}
object A extends Conflictor {}
class B extends A with Conflictor {}
Something else ;)