1

Taking the following class and interface:

public class A {
    public int foo() {
        return 1;
    }
}

public interface B {
    default int foo() {
        return 2;
    }
}

If you define a sublclass in java like that

public class C extends A implements B {
}

Calling foo on an instance of C will return 1, as java prefers the superclass over the interface.

Doing the same thing in scala gives a compile error:

class D extends A with B

Error:(3, 9) class D inherits conflicting members:
  method foo in class A of type ()Int  and
  method foo in trait B of type ()Int
(Note: this can be resolved by declaring an override in class D.)

Manually overriding the method

class D extends A with B {
  override def foo(): Int = super.foo()
}

Still gives incorrect behaviour, calling foo on an instance of D will return 2.

To get a scala class to behave the same way as java in this case you have manually override every single method and specify A as the superclass in every call.

class D extends A with B {
  override def foo(): Int = super[A].foo()
}

Why was it implemented like that? And is there a reasonable way to work around it, without manually overriding every method in that situation?

bdew
  • 1,330
  • 9
  • 22
  • Short answer : Scala supports multiple inheritance while Java does not. And hence they had to make some different design decisions with inheritance chains. For a simple and detailed explanation - https://www.safaribooksonline.com/blog/2013/05/30/traits-how-scala-tames-multiple-inheritance/ – sarveshseri Feb 21 '17 at 14:15
  • See also http://stackoverflow.com/questions/19153088/in-scala-multiple-inheritance-how-to-resolve-conflicting-methods-with-same-sign – slouc Feb 21 '17 at 14:16
  • @slouc i think that question is about something different. I'm asking about method resolution order differences between scala and java, while that question is about inheriting from conflicting types in scala. – bdew Feb 21 '17 at 14:44
  • @SarveshKumarSingh Thanks for the link. Thing is, now java has kinda-multiple-inheritance with default implementation in interfaces. And it works differently making interoperability harder when using java libraries from scala. – bdew Feb 21 '17 at 14:48
  • No... It does not make it harder. Just different. As it should be expected with Scala being a different language. And please stop thinking of Scala as Java++ or better Java, it is a whole different language and hence accept the differences. – sarveshseri Feb 21 '17 at 14:57
  • Well, Scala was first to design traits, which are more powerful than default methods. When default methods came to the JVM you can't really expect Scala to adapt their linearization algorithms and probably completely break existing code because Java chose a different strategy. – Jasper-M Feb 21 '17 at 14:57
  • And in the end, there is no big issue with Java interop. Interop doesn't mean: take Java code, delete `public`, change `implements` to `with`, add `def` before methods, change `<>` to `[]`, and compile. It would be confusing if interfaces coming from Java were treated as completely different concepts than traits in Scala. – Jasper-M Feb 21 '17 at 15:02

0 Answers0