Java поддерживает "мягкие" интерфейсы? - PullRequest
0 голосов
/ 27 сентября 2018

Рассмотрим следующий сценарий: допустим, вы создали интерфейс Foo:

public interface Foo {

    public void bar();

}

и скажите, что в определенной библиотеке, которую вы хотите использовать, есть старый класс SomeOldClass.У него уже есть метод bar(), но он явно не реализует Foo.

. Вы написали следующий код для всех классифицированных, которые реализуют Foo:

public <T extends Foo> T callBarOnThird(List<T> fooList){
    return fooList.get(2).bar();
}

А теперьВы хотите, чтобы это также работало для SomeOldClass.У вас нет доступа к исходному коду этого класса, поэтому вы не можете его изменить.

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

Ответы [ 3 ]

0 голосов
/ 27 сентября 2018

Расширение до ответа Thilos.

Вы также можете использовать декоратор для обработки этого

public <T extends Foo> T callBarOnThird(List<T> fooList){
    return new BarDecorator(fooList.get(2)).bar();
}

Внутри декоратора вы можете проверить, является ли данный объект экземпляром Foo или нет, тогдаделать операции соответственно.

0 голосов
/ 27 сентября 2018

Java статически типизирован и динамически связывать .

Динамически связывать: Это означает, что связь между сигнатурой метода и его реализация происходит во время выполнения.Например.

Например

public interface MyInterface {

    void doStuff();

}

public class MyFirstImpl implements MyInterface {

   @Override
   public void doStuff() {
       // do some stuff here
   }

}

public class MySecondImpl implements MyInterface {

   @Override
   public void doStuff() {
       // do some stuff here
   }

}

Так что, если у вас будет следующий фрагмент

MyInterface test; // pointing to either MyFirstImpl or MySecondImpl 
test.doStuff();

JVM определит во время выполнения погоду для вызова doStuffметод из MyFirstImpl или MySecondImpl в зависимости от типа объекта во время выполнения.

Статически напечатано: Это означает, что JVM проверит во время компиляции, существует ли метод дляЗвоните независимо от реализации.

Например:

public interface MyInterface {

    void doStuff();

}

public class MyFirstImpl implements MyInterface {

   // no override here
   public void doStuff() {
       // do some stuff here
   }

}

public class MySecondImpl implements MyInterface {

   // no override here
   public void doStuff() {
       // do some stuff here
   }

}

Так что, если у вас будет следующий фрагмент

MyInterface test; // pointing to either MyFirstImpl or MySecondImpl 
test.doStuff();

Компилятор будет жаловаться, потому что он не может гарантировать во время компиляции, что независимореализации MyInterface есть метод doStuff для вызова (хотя в этом случае обе реализации MyInterface определяют метод doStuff).

Это гарантирует, что вы не получитеNoSuchMethodException во время выполнения, если вы пропустите, например, следующую реализацию.

public class MySecondImpl implements MyInterface {

   // no override here
   // no doStuff method

}

Это добавляет некоторую безопасность типов к языку ценой некоторой жесткости (поскольку вы можете определитьвыпускать раньше, чем во время выполнения, и поэтому у вас более короткий цикл обратной связи, за счет сценария, в котором все реализации фактически предоставляют метод, не работающий «из коробки».

Как следует выполнить рефакторингВаш код:

Создайте оболочку над сторонней библиотекой и откройте интерфейс из оболочки.

public interface Foo {

    void bar();

}

public class ThirdPartyFooWrapper implements Foo {

     private SomeOldClass oldClass;

     public ThordPartyFooWrapper (SomeOldClass oldClass){
          this.oldClass = oldClass;
     }

     @Override
     public void bar() {
         this.oldClass.bar();
     }

}

Затем в своем коде используйте ThirdPartyFooWrapper вместо SomeOldClass.

Надеюсь, это ответит на ваш вопрос!

0 голосов
/ 27 сентября 2018

Нет, это не так.

Вы должны предоставить экземпляр адаптера (есть несколько методов и инструментов, чтобы помочь с этим, но Java не делает это "неявно").

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