Ковариантный тип возврата в интерфейсе не компилируется через Javac - PullRequest
9 голосов
/ 14 августа 2011

У меня есть следующая структура:

public interface BarReturn {}
public interface FooReturn {}
public interface FooBarReturn extends FooReturn, BarReturn {}

public interface Foo {  
  FooReturn fooBar( );
}

public interface Bar {
  BarReturn fooBar();
}

public interface FooBar extends Foo, Bar {
  FooBarReturn fooBar();
}

Сбой Javac со следующим сообщением:

FooBar.java:2: types Bar and Foo are incompatible; both define fooBar(), but with unrelated return types
public interface FooBar extends Foo, Bar {
       ^
1 error

Однако Eclipse может скомпилировать его нормально, и, насколько я вижу, он должен скомпилироваться - метод fooBar () FooBar удовлетворяет контракту как метода Foo, так и метода fooBar () Бара с помощью ковариантных возвращений.

Это ошибка в компиляции Eclipse или в javac? Или есть способ убедить javac скомпилировать его? Для справки мои параметры javac выглядят так:

* * 1010

Ответы [ 6 ]

3 голосов
/ 14 августа 2011

Вы расширяете Foo и Bar в своем интерфейсе FooBar. Таким образом, вы наследуете два метода с несовместимыми типами возврата. Java-дисперсия допускается только тогда, когда она следует за подстановкой Лискова. Ака, переопределяющие типы кандидатов должны быть в значительной степени подклассом переопределенного возвращаемого типа.

В вашем примере выше что-то подобное должно скомпилировать:

public interface BarReturn {}
public interface FooReturn {}
public interface FooBarReturn extends FooReturn, BarReturn {}

public interface Foo {  
  FooReturn fooBar( );
}

public interface FooBar extends Foo{
  FooBarReturn fooBar();
}
1 голос
/ 16 мая 2012

У меня была такая же проблема, и, кажется, все хорошо, если использовать JDK 7 от Oracle.

1 голос
/ 14 августа 2011

В качестве обходного пути, вы можете сделать

interface Foo1 extends Foo {
  FooBarReturn fooBar();
}
interface Bar1 extends Bar {
  FooBarReturn fooBar();
}
public interface FooBar extends Foo1, Bar1 { }

Не красиво, но должно сработать.

1 голос
/ 14 августа 2011

Ответ в этом обсуждении javaranch , похоже, предполагает, что это ошибка javac. Однако ссылка на ссылка , на которую есть ссылка, не работает.

1 голос
/ 14 августа 2011

JLS (§9.4.1) говорит:

Интерфейс может наследовать несколько методов с эквивалентные по переопределению подписи (§8.4.2). Такая ситуация не в сам вызывает ошибку времени компиляции. Интерфейс считается наследовать все методы. Однако один из унаследованных методов должен должен быть возвращаемым типом, заменяемым для любого другого унаследованного метода; в противном случае возникает ошибка времени компиляции (предложения throws не вызвать ошибки в этом случае.)

Так что я бы сказал, что Джавак прав. Но для меня это похоже на юридический жаргон, поэтому я могу ошибаться.

0 голосов
/ 24 июня 2013
...