bug icon indicating copy to clipboard operation
bug copied to clipboard

AbstractMethodError when overriding java method with default implementation which implementation is "muted" in inherited interface

Open unkarjedy opened this issue 5 years ago • 4 comments

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; }
}

unkarjedy avatar Nov 10 '20 11:11 unkarjedy

related: https://youtrack.jetbrains.com/issue/SCL-18412

unkarjedy avatar Nov 10 '20 11:11 unkarjedy

Is getText necessary to reproduce?

Jasper-M avatar Nov 10 '20 11:11 Jasper-M

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.

dwijnand avatar Nov 10 '20 12:11 dwijnand

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...

Jasper-M avatar Nov 10 '20 14:11 Jasper-M