Как я могу сделать интерфейс в Java с функцией, которая принимает параметр типа, который расширяет интерфейс? - PullRequest
0 голосов
/ 21 февраля 2019

Как я могу сделать интерфейс в Java с функцией, которая принимает параметр типа, который расширяет интерфейс?

Например, возьмем интерфейс ISelfComparable

, если класс A расширяет его, тоя ожидал бы, что он реализует

bool compareTo(A other)

, но если класс B расширяет его, тогда я ожидал бы, что он реализует

bool compareTo(B other)

Я знаю, что могу использовать универсальный интерфейс, но это неверно, потому чтодля A не имеет никакого смысла расширять ISelfComparable

Если это невозможно, какова лучшая практика в такой ситуации?

Ответы [ 3 ]

0 голосов
/ 21 февраля 2019

Посмотрите на класс java.lang.Comparable: у него есть аргумент с типом объектов, которые могут использоваться int compareTo.

По аналогии:

public interface ISelfComparable<T extends ISelfComparable<T>> {
    boolean compareTo(T other);
}
0 голосов
/ 21 февраля 2019

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

interface ISelfComparable {
    default boolean compareTo(ISelfComparable param) {
        if (this.getClass() != param.getClass()) {
            throw new IllegalArgumentException();
        }
        ...
    }
}

Тогда каждая реализация этого интерфейса должна выглядеть следующим образом:

class A implements ISelfComparable {
    @Override
    public  boolean compareTo(ISelfComparable param) {
        ISelfComparable.super.compareTo(param);
        ...
    }
}

В этом случае, если вы вызываете new A().compareTo(new B());, тогдаjava.lang.IllegalArgumentException будет брошено

0 голосов
/ 21 февраля 2019

Обычное решение - самоограниченные дженерики, как видно из класса Enum.

interface Example<T extends Example<T>> {
    void foo(T t);
}

public class ExampleImpl implements Example<ExampleImpl> {
    @Override
    public void foo(ExampleImpl example) {
    }
}

Как это работает, немного головокружительно, но очень хорошо объяснено здесь например.Здесь также есть очень хороший ответ по этому вопросу здесь .

Обратите внимание, что он не является надежным, поскольку допускает следующее:

public class ExampleImpl2 extends Example<ExampleImpl {
    @Override
    public void foo(ExampleImpl example) {

    }
}

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

Если вам действительно очень нужен объект параметра, чтобы он всегда был точно таким же классом, как this, вы должнысделать проверку во время выполнения.(Это также поднимает вопрос о том, зачем вам это нужно, но это отвлечет нас от темы.)

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