Поскольку в Java есть номинальная типизация, так что org.theirs.Foo
никак не связан с org.yours.Foo
, даже если они имеют одинаковые сигнатуры методов, я не думаю, что это возможно сделать с наследованием в Java. AFAIK не может сказать, что даже при использовании дженериков «этот метод использует экземпляр Bar<T extends Foo OR Bar>
».
Вместо этого, я думаю, вы хотите использовать интерфейс адаптера для библиотеки Foo
, со своей собственной (т. Е. FooAdapter
, имеющей те же подписи, что и Foo
), и иметь это продлить Bar
. Методы, которые вы хотите в Bar
, можно затем извлечь из FooAdapter
. К сожалению, ваш код придется изменить так, чтобы везде вы ранее ссылались на их Foo
, вместо этого вы должны ссылаться либо на:
Bar
если вызваны только те методы, которые вы определили бы в своем интерфейсе
FooAdapter
если вызываются методы, определенные в Foo
, но НЕ в Bar
.
Этот метод, хотя и чистый, но с хорошим разделением интересов, может быть болезненным и утомительным для реализации, я боюсь.
Пример того, как это будет работать, показан в следующих фрагментах кода:
Сторонняя библиотека
package org.theirs;
public interface Foo {
void doSomething();
void doSomethingExtra();
}
Ваш код
package org.mine;
public interface Bar {
void doSomething();
}
public class BarImpl implements Bar{
public void doSomething( /* implementation */ );
}
public class FooAdapter implements Bar{
private final Foo adapted;
public FooAdapter(Foo adapted) {
this.adapted = adapted;
}
public void doSomething() {
adapted.doSomething(); // delegate to adapted instance
}
}
public class UsingThoseBars {
public void doSomethingWithAllThoseBars(Collection<Bar> bars) {
// each entry in bars could either be a BarImpl or a FooAdapter
}
}
Из этого примера видно, что метод doSomethingExtra()
недоступен из вашего кода, поскольку интерфейс Bar
не указывает его.
Другие предложения
Обратите внимание, что при переписывании классов могут быть полезны некоторые приемы, такие как AspectJ. Я предполагаю, что вы предпочли бы получить желаемый эффект во время компиляции, на чистой Java.
Другим предложением является реализация Bar
, которая выдает UnsupportedOperationException
для методов Foo
, которые вам не нужны. Хотя в крупных библиотеках Java есть прецедент для этого (например, UnmodifiableList
в JDK), я бы рекомендовал вообще отказаться от этой практики. Однако, если стоимость замены ссылок на их Foo
на новые FooAdapter
достаточно высока, использование этой стратегии может быть хорошим компромиссом.