Почему scala обрабатывает методы по умолчанию в интерфейсах java иначе, чем сама java?

Взяв следующий класс и интерфейс:

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

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

Если вы определяете подкласс в java, как это

public class C extends A implements B {
}

Вызов foo для экземпляра C вернет 1, поскольку java предпочитает суперкласс интерфейсу.

Выполнение того же самого в scala дает ошибку компиляции:

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

Ручное переопределение метода

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

Все еще дает неправильное поведение, вызов foo для экземпляра D вернет 2.

Чтобы в этом случае класс scala вел себя так же, как java, вы вручную переопределяете каждый метод и указываете A в качестве суперкласса в каждом вызове.

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

Почему так реализовано? И есть ли разумный способ обойти это, не переопределяя вручную каждый метод в этой ситуации?


person bdew    schedule 21.02.2017    source источник
comment
Краткий ответ: Scala поддерживает множественное наследование, а Java — нет. И, следовательно, им пришлось принять несколько разных проектных решений с цепочками наследования. Простое и подробное объяснение — safaribooksonline.com/blog/2013/05/30/   -  person sarveshseri    schedule 21.02.2017
comment
См. также stackoverflow.com/questions/19153088/   -  person slouc    schedule 21.02.2017
comment
@slouc я думаю, что этот вопрос о чем-то другом. Я спрашиваю о различиях в порядке разрешения методов между scala и java, в то время как этот вопрос касается наследования от конфликтующих типов в scala.   -  person bdew    schedule 21.02.2017
comment
@SarveshKumarSingh Спасибо за ссылку. Дело в том, что теперь java имеет своего рода множественное наследование с реализацией по умолчанию в интерфейсах. И это работает по-другому, что усложняет взаимодействие при использовании java-библиотек из scala.   -  person bdew    schedule 21.02.2017
comment
Нет... Это не усложняет задачу. Просто другой. Как и следовало ожидать, поскольку Scala является другим языком. И, пожалуйста, перестаньте думать о Scala как о Java++ или лучше о Java, это совершенно другой язык и, следовательно, примите различия.   -  person sarveshseri    schedule 21.02.2017
comment
Что ж, Scala первой разработала трейты, которые более эффективны, чем методы по умолчанию. Когда в JVM появились методы по умолчанию, нельзя было ожидать, что Scala адаптирует свои алгоритмы линеаризации и, возможно, полностью сломает существующий код, потому что Java выбрала другую стратегию.   -  person Jasper-M    schedule 21.02.2017
comment
И, в конце концов, нет большой проблемы с взаимодействием Java. Взаимодействие не означает: взять код Java, удалить public, заменить implements на with, добавить def перед методами, изменить <> на [] и скомпилировать. Было бы запутанно, если бы интерфейсы, пришедшие из Java, рассматривались как совершенно другие понятия, чем трейты в Scala.   -  person Jasper-M    schedule 21.02.2017