Java - коллизия Имени метода в интерфейсной реализации

Если у меня есть два интерфейса, оба очень отличающиеся в их целях, но с той же сигнатурой метода, как я заставляю класс реализовать обоих, не будучи вынужденным записать отдельный метод, который служит для и интерфейсы и пишущий некоторую замысловатую логику в реализации метода, которая проверяет, для которого типа объекта вызов выполняется и вызывает надлежащий код?

В C# это преодолено тем, что называют как явная интерфейсная реализация. Есть ли в Java какой-либо эквивалентный путь?

86
задан YCF_L 28 March 2017 в 11:04
поделиться

3 ответа

Нет, в Java невозможно реализовать один и тот же метод двумя разными способами в одном классе.

Это может привести к множеству запутанных ситуаций, поэтому Java не разрешает это.

interface ISomething {
    void doSomething();
}

interface ISomething2 {
    void doSomething();
}

class Impl implements ISomething, ISomething2 {
   void doSomething() {} // There can only be one implementation of this method.
}

Что вы можете сделать, так это составить класс из двух классов, каждый из которых реализует свой интерфейс. Тогда этот один класс будет иметь поведение обоих интерфейсов.

class CompositeClass {
    ISomething class1;
    ISomething2 class2;
    void doSomething1(){class1.doSomething();}
    void doSomething2(){class2.doSomething();}
}
73
ответ дан 24 November 2019 в 08:06
поделиться

Реального способа решить эту проблему в Java нет. Вы можете использовать внутренние классы в качестве обходного пути:

interface Alfa { void m(); }
interface Beta { void m(); }
class AlfaBeta implements Alfa {
    private int value;
    public void m() { ++value; } // Alfa.m()
    public Beta asBeta() {
        return new Beta(){
            public void m() { --value; } // Beta.m()
        };
    }
}

Хотя он не позволяет преобразовывать из AlfaBeta в Beta , понижающие преобразования обычно являются злом, и если можно ожидать, что Экземпляр Alfa часто также имеет аспект бета , и по какой-то причине (обычно оптимизация является единственной веской причиной) вы хотите иметь возможность преобразовать его в бета , вы можете создать субинтерфейс Alfa с Beta asBeta () в нем.

13
ответ дан 24 November 2019 в 08:06
поделиться

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

Чтобы дать конкретный пример для последнего случая, предположим, что вы хотите реализовать как Collection , так и MyCollection (который не наследуется от Collection и имеет несовместимый интерфейс). Вы можете предоставить функции Collection getCollectionView () и MyCollection getMyCollectionView () , которые обеспечивают облегченную реализацию Collection и MyCollection , используя те же базовые данные.

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

11
ответ дан 24 November 2019 в 08:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: