Когда я расширю интерфейс A интерфейсом B, будут ли методы A доступны бесплатно для разработчиков B? - PullRequest
0 голосов
/ 01 февраля 2020

Мне любопытно, как все это работает. У меня есть интерфейс, давайте назовем его A. Когда я смотрю на A, он имеет большинство необходимых мне методов, но не все, и у меня нет контроля над интерфейсом A, поэтому я расширяю его интерфейсом B, который реализует 1 или любое другое число методов, которые мне нужны поверх A.

public interface B extends A {

    String doSomethingFun(String blah);

}

A имеет класс реализации с именем Client. Через секунду я собираюсь создать свой собственный класс реализации B с именем MyDefaultClient.

Затем я создам конкретный класс, который реализует B, например:

@Component
public class MyDefaultClient implements B {

    private A myClient;

    @Autowired
    public MyDefaultClient(A myClient) {
        this.myClient = myClient;
    }

    @Override
    public String doSomethingFun(String filename) {
        // custom business logic
    }

    @Override
    public String serviceName() {
        return myClient.serviceName();
    }

    @Override
    public void close() {
        myClient.close();
    }

}

serviceName() и close() - это методы, которые A заставляет своих разработчиков реализовывать. Хотя есть и другие методы, которые имеют реализации по умолчанию, которые не заставляют меня их реализовывать, я полагаю, просто потому, что они имеют реализации по умолчанию.

На данный момент у меня есть конкретный класс, который я могу создать в других местах и вызовите все методы A и B. Но это только потому, что в интерфейсе есть реализации по умолчанию для этих методов, например, вот так?

default Blah someMethodInA(String thing) {
    throw new UnsupportedOperationException();
}

Если я использую этот код и вызываю myDefaultClient.doSomethingFun("hello"), я почти уверен, что сделаю то, что хочу это делать. Но что если я позвоню myDefaultClient.someMethodInA()? Будет ли он вызывать реализованный метод в Client, который является A разработчиком? Или он упадет на пол и пожалуется на UnsupportedOperationException? Если последнее, есть ли какой-нибудь способ, которым я могу структурировать это так, чтобы я мог вызывать все методы A из реализации B?

Ответы [ 3 ]

0 голосов
/ 01 февраля 2020

Интерфейс может иметь любое количество default методов. Проверьте это для более подробной информации. Ниже приведен пример, демонстрирующий, как default методы и расширение interface работают:

public interface InterfaceA {
    public void toBeImplementedA();

    default void hello() {
        System.out.println("Hello");
    }

    default void hi() {
        System.out.println("Hi");
    }
}


public interface InterfaceB extends InterfaceA {
    public void toBeImplementedB();
}


public class AnImplClass implements InterfaceB {

    @Override
    public void toBeImplementedA() {
        System.out.println("toBeImplementedA");
    }

    @Override
    public void toBeImplementedB() {
        System.out.println("toBeImplementedB");
    }
}


public class Main {
    public static void main(String[] args) {
        InterfaceB obj = new AnImplClass();
        obj.toBeImplementedA();
        obj.toBeImplementedB();
        obj.hello();
        obj.hi();
    }
}

Вывод:

toBeImplementedA
toBeImplementedB
Hello
Hi

Не стесняйтесь комментировать в случае каких-либо сомнений.

0 голосов
/ 01 февраля 2020

Если вы хотите, чтобы MyDefaultClient - наследовали реализации от Client, тогда оно должно расширяться Client, например:

class MyDefaultClient extends Client implements B
{
    ...
}

Тогда, если Client implements A вам нужно будет только предоставить реализации для новых методов, которые добавляет B.

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

0 голосов
/ 01 февраля 2020

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

Методы по умолчанию предоставляют реализацию, если ваш класс реализации не реализует их.

Когда Вы вызываете методы объекта, всегда вызывается переопределенный метод.

Любые другие реализации в суперклассах / интерфейсах используются, когда отсутствует реализация.

Даже если вы ссылаетесь на MyDefaultClient как A,

A myImplementation = new MyDefaultClient();

В капот myImplementation все еще является экземпляром MyDefaultClient, хотя код рассматривает его как A. Поэтому ваш переопределенный метод будет использоваться при вызове doSomethingFun.

    @Override
    public String doSomethingFun(String filename) {
        // custom business logic
    }

¹ Источник: https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html

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