Last active
December 12, 2015 00:28
-
-
Save ogirardot/4683919 to your computer and use it in GitHub Desktop.
Simple gist to show problem when using companion object extending trait and sub-class using the same trait
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 {} |
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 {}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Btw : It fails in scala 2.9.2, it works in scala 2.10.0. Interesting.