Если у меня есть два интерфейса, оба очень отличающиеся в их целях, но с той же сигнатурой метода, как я заставляю класс реализовать обоих, не будучи вынужденным записать отдельный метод, который служит для и интерфейсы и пишущий некоторую замысловатую логику в реализации метода, которая проверяет, для которого типа объекта вызов выполняется и вызывает надлежащий код?
В C# это преодолено тем, что называют как явная интерфейсная реализация. Есть ли в Java какой-либо эквивалентный путь?
Нет, в 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();}
}
Реального способа решить эту проблему в 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 ()
в нем.
Если вы столкнулись с этой проблемой, скорее всего, вы используете наследование там, где вы должны использовать делегирование . Если вам нужно предоставить два разных, хотя и похожих, интерфейса для одной и той же базовой модели данных, тогда вам следует использовать представление , чтобы дешево обеспечить доступ к данным с помощью какого-либо другого интерфейса.
Чтобы дать конкретный пример для последнего случая, предположим, что вы хотите реализовать как Collection
, так и MyCollection
(который не наследуется от Collection
и имеет несовместимый интерфейс). Вы можете предоставить функции Collection getCollectionView ()
и MyCollection getMyCollectionView ()
, которые обеспечивают облегченную реализацию Collection
и MyCollection
, используя те же базовые данные.
В первом случае ...предположим, вам действительно нужен массив целых чисел и массив строк. Вместо наследования как List
, так и List
, у вас должен быть один член типа List
и другой член типа Список
,и обращаться к этим членам, а не пытаться наследовать от обоих. Даже если вам нужен только список целых чисел, в этом случае лучше использовать композицию / делегирование вместо наследования.