проблема с подстановочными знаками и одним классом, который реализует два интерфейса - PullRequest
0 голосов
/ 14 июля 2010

У меня есть этот вопрос.У меня есть class UserImpl implements MyUser, YourUser и class UsersGetterImpl implements MyUsersGetter, YourUsersGetter.Я хочу реализовать метод внутри UsersGetterImpl, который возвращает List<MyUser> getUsers() для MyUsersGetterinterface и List<YourUser> getUsers() для YourUsersGetterinterface, но я не могу понять, каким должен быть тип возврата getUsers() внутри UsersGetterImplкласс - вероятно, это должно быть что-то с подстановочными знаками (например, List<? extends UserImpl> getUsers(), но не совсем, потому что этот пример не будет работать ...)

Ответы [ 2 ]

2 голосов
/ 14 июля 2010

Трудно сказать, о чем вы спрашиваете, но в соответствии с Спецификацией языка Java :

В такой ситуации:

interface Fish { int getNumberOfScales(); }
interface StringBass { double getNumberOfScales(); }
class Bass implements Fish, StringBass {
    // This declaration cannot be correct, no matter what type is used.
    public ??? getNumberOfScales() { return 91; }
}

Невозможно объявить метод с именем getNumberOfScales с такой же сигнатурой и типом возврата, что и у обоих методов, объявленных в интерфейсе Fish и в интерфейсе StringBass, поскольку класс может иметь только один метод с заданнымподпись (§8.4).Поэтому для одного класса невозможно реализовать как интерфейс Fish, так и интерфейс StringBass.

Однако, если оба ваших интерфейса задают один и тот же тип возврата, вы можете продолжить и реализовать этот метод.Если у MyUser и YourUser есть общий предок, вы можете сделать List<? extends User> или если у них нет общности, которую вы можете использовать, просто используйте List<?>.

В этот момент вы должны остановиться и рассмотретьесли общая реализация это то, что вы на самом деле хотите.Я подозреваю, что может быть более элегантное решение, если вы предоставили нам более подробную информацию о вашей проблеме.

Редактировать:

На основании вашего комментария вы хотите что-то вроде...

interface MyUserGetter { List<? extends MyUser> getUsers(); }
interface YourUserGetter { List<? extends YourUser> getUsers(); }
class UserGetterImpl { List<? extends UserImpl> getUsers(); }

Это не проверено, и я предполагаю, что с вероятностью 50% будет работать.

Архитектурное предложение состоит в том, что вместо одной реализации для двух интерфейсов вына самом деле может потребоваться две реализации одного интерфейса:

interface User {}
class MyUser implements User {}
class YourUser implements User {}
interface UserGetter { List<? extends User> getUsers(); }
1 голос
/ 14 июля 2010

Короткий ответ: это невозможно.У вас не может быть двух методов, чья сигнатура отличается только типом возвращаемого значения, и поэтому у вас не может быть одного класса, реализующего два интерфейса, которые определяют методы, отличающиеся только типом возвращаемого значения.

Простое решение состоит в том, чтобы MyUsersGetter и YourUsersGetter имели методыс разными именами.

Одним из возможных способов решения этой проблемы было бы то, что UsersGetterImpl не реализует MyUsersGetter и YourUsersGetter напрямую, но имеет делегатов:

class UsersGetterImpl {
  public MyUsersGetter getMyUsers () {
    return new MyUsersGetter () {
      public List<MyUsers> getUsers () {
        //do stuff here
      }
    }
  }
...