Сделайте так, чтобы метод класса, использующий дженерики, мог возвращать как свои, так и свои экземпляры подклассов. - PullRequest
1 голос
/ 05 октября 2019

Я реализовал следующие классы Java:

public class Data<T> {

    private List<T> data;

    public List<T> getData() {
        return this.data;
    }


    public Data<T> setData(List<T> data) {
        this.data = data;
        return this;
    }

    public Data<T> getAsNullIfEmpty() {
        if (this.data == null || this.data.isEmpty())
            return null;
        return this;
    }

}
public class IntegerData extends Data<Integer> {}

Я бы хотел, чтобы метод getAsNullIfEmpty() мог вызываться его экземплярами подклассов.

В строке IntegerData integerData = new IntegerData().getAsNullIfEmpty(); выдается следующая ошибка компиляции: incompatible types: Data<java.lang.Integer> cannot be converted to IntegerData

Я попытался изменить тело метода getAsNullIfEmpty() на следующее:

public <E extends Data<T>> E getAsNullIfEmpty() {
    if (this.data == null || this.data.isEmpty())
        return null;
    return this;
}

Thisне компилируется, потому что Data<T> не расширяет себя. Есть ли способ сделать это, не возвращаясь к переопределению метода в каждом из дочерних классов или не используя явное приведение?

1 Ответ

2 голосов
/ 05 октября 2019

Вам нужен «обычный» трюк, чтобы дженерики класса ссылались на себя, плюс небезопасное приведение.

public class Data<T, D extends Data<T, D>> {

    private List<T> data;

    public List<T> getData() {
        return this.data;
    }


    public D setData(List<T> data) {
        this.data = data;
        return (D) this;
    }

    public D getAsNullIfEmpty() {
        if (this.data == null || this.data.isEmpty())
            return null;
        return (D) this;
    }

}
public class IntegerData extends Data<Integer, IntegerData> { ... }
...