Java - для заданной функции foo (X i); в интерфейсе X почему реализация класса Y не может изменить его на foo (Y i)? - PullRequest
0 голосов
/ 30 марта 2010

Например

public interface X{
    public void foo(X i);
}

public class Y implements X{//error: doesn't implement foo(X i)...
    public void foo(Y i){
        fooBar(foo);
    }
    ....
}

Почему я не могу этого сделать? И как я могу изменить это так, чтобы это было возможно? Что я могу сделать, чтобы объявить foo в X с параметром, а затем иметь возможность использовать Y в качестве типа параметра в Y?

Ответы [ 6 ]

4 голосов
/ 30 марта 2010

В дополнение к тому, что сказал Дон Бойл, вы не можете изменить его, не намекая на компилятор намерения. Вы делаете это, вводя Generics в интерфейс, например так:

public interface X<T> {
    public void foo(T i);
}

public class Y implements X<Y> {
    public void foo(Y i){
        fooBar(foo);
    }
}
4 голосов
/ 30 марта 2010

Изменяя тип входного параметра в классе Y, вы изменили сигнатуру метода, что означает, что компилятор видит его как совершенно другой метод.

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

2 голосов
/ 30 марта 2010

Попробуйте что-то вроде

interface X<T extends X> {
    public void foo(T a);
}

class Y implements X<Y> {
    public void foo(Y a);
}
1 голос
/ 30 марта 2010

Предположим, вы сделали так, как хотите, и предположим, что Java разрешил это.И скажем, другой класс - назовите его Z - также реализует X. Поскольку Z реализует X, и из-за определения X вы должны иметь возможность вызывать X.foo (z) для любого Z z.Но Y, который является X, не знает, что делать, если вы передадите Z его foo ().Вот почему.

0 голосов
/ 30 марта 2010

Потому что интерфейс определяет общее поведение для всех реализующих классов. Допустим, у вас есть некоторые другие классы, все реализующие X, вы ожидаете, что если у вас есть объект класса X, вы можете вызвать foo с параметром класса X (который может быть любым из его подклассов или реализаций), так что давайте скажем: иметь такой код:

class Z implements X {
  ...
}

Z z = new Z();
X x = new Y();
x.foo(z);

Что было бы ложным, поскольку с вашим кодом foo будет принимать только аргументы класса Y

0 голосов
/ 30 марта 2010

Реализуя интерфейс X, вы обещаете, что реализуете все методы этого интерфейса, а это значит, что ваш метод foo может принимать произвольный X. Теперь, если вы просто примете Ys в качестве параметра для вашего метода foo, вы не сможете полностью реализовать интерфейс, так как все другие классы, реализующие X, не являются допустимыми параметрами для foo.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...