Ограничение объявления подкласса - PullRequest
2 голосов
/ 02 августа 2011

У меня есть приложение, в котором я хочу, чтобы все мои классы моделей реализовывали определенный метод update. Для этого я создал abstract class и interface со следующим объявлением:

public interface BaseInterface<T>
{
    T update(T t);
}

public abstract class BaseClass<T extends BaseClass<T>> implements BaseInterface<T>
{

}

Следовательно, все мои классы моделей будут расширяться BaseClass. Например, определение класса Book будет

public class Book extends BaseClass<Book>
{
    public Book update(Book b)
    {
        //implementation
    }
}

Однако, используя вышеупомянутую конструкцию, я не могу ограничить объявления моих модельных классов. Например, хотя это допустимо и требуется для класса Book для расширения BaseClass<Book>, также допустимо следующее объявление:

class Book extends BaseClass<User>
{
    public User update(User u)
    {
        //implementation
    }
}

Хотя синтаксически правильно делать вышеуказанное, я хочу ограничить это.

По сути, я хочу, чтобы метод update моих классов моделей взял в качестве параметра экземпляр своего собственного класса и возвратил экземпляр своего собственного класса и ничего больше.

Другими словами, если существует класс C, который расширяет BaseClass, то его update метод должен иметь точную сигнатуру C update(C c).

Или, другими словами, если существует класс C, который расширяет BaseClass, то параметром шаблона для BaseClass должен быть C сам по себе [то есть C extends BaseClass<C>] и ничего больше.

Как мне этого добиться?

ПРИМЕЧАНИЕ. Это несколько похоже на объявление enum

.
public class Enum<E extends Enum<E>> implements Comparable<E>
{
    int compareTo(E e)
    {
    }
}

Здесь мы можем ограничить определение метода compareTo принятием экземпляра его собственного типа enum, а не любого другого типа enum.

Заранее спасибо.

1 Ответ

2 голосов
/ 02 августа 2011

Измените определение вашего интерфейса на interface BaseInterface<T extends BaseClass<T>>.

Пожалуйста, следуйте моему примеру:

public interface BaseInterface<T extends BaseClass<T>> {
    T update(T t);
}

public abstract class BaseClass<T extends BaseClass<T>> implements
        BaseInterface<T> {

}

public class Book extends BaseClass<Book> {
    @Override
    public Book update(Book b) {
        return null;
    }
}

class User {}

    // This code cannot be compiled exactly for reason you want.
public class Book2 extends BaseClass<User> {
    @Override
    public Book2 update(Book2 b) {
        return null;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...