bug
bug copied to clipboard
AbstractMethodError when overriding java method with default implementation which implementation is "muted" in inherited interface
reproduction steps
using Scala (2.13.3),
public interface BaseRootJava {
default boolean startInWriteAction() {
return true;
}
}
public interface BaseIntermidiateJava extends BaseRootJava {
String getText();
@Override
boolean startInWriteAction();
}
class ChildScala extends BaseIntermidiateJava {
override def getText: String = ""
}
object Main {
def main(args: Array[String]): Unit = {
val action = new ChildScala
println(action.startInWriteAction())
}
}
problem
This code compiles but throws an error at runtime:
Exception in thread "main" java.lang.AbstractMethodError: Method MyIntentionActionScala.startInWriteAction()Z is abstract
at MyIntentionActionScala.startInWriteAction(MyIntentionActionScala.scala)
at Main$.main(Main.scala:5)
at Main.main(Main.scala)
java analog will not compile
public class ChildJava implements BaseIntermidiateJava {
@Override
public String getText() { return null; }
}
related: https://youtrack.jetbrains.com/issue/SCL-18412
Is getText necessary to reproduce?
I think it should "do the right thing" (return true), but if javac doesn't compile it perhaps it does so for a good reason, worth following.
I think it should "do the right thing"
There doesn't seem to be agreement on what the right thing is.
Scala 2.13
scala> trait Foo { def foo = "foo" }
| trait Bar extends Foo { override def foo: String }
| class Baz extends Bar
trait Foo
trait Bar
class Baz
Dotty (lampepfl/dotty#4770)
scala> trait Foo { def foo = "foo" }
| trait Bar extends Foo { override def foo: String }
| class Baz extends Bar
3 |class Baz extends Bar
| ^
| class Baz needs to be abstract, since override def foo: => String is not defined
I've never quite understood the reasoning behind Scala 2's behavior actually...