Обобщенный класс и проблема наследования - PullRequest
1 голос
/ 17 декабря 2010

У меня есть родительский класс Builder, который можно сгенерировать с помощью параметра типа Builder или его подтипа:

class Builder<T extends Builder> {

    @SuppressWarnings("unchecked")
    T doSmth() {
        System.out.println("do smth");
        return (T)this;
    }
}

Имеет подкласс - BuilderChild:

class BuilderChild extends Builder<BuilderChild> {

    BuilderChild doSmthElse() {
        System.out.println("do smth else");
        return this;
    }
}

Итак, я могу вызвать метод doSmth на экземпляре BuilderChild и он вернет BuilderChild:

new BuilderChild().doSmth().doSmthElse();

Но когда я попытался сгенерировать BuilderChild, строка выше перестала компилироваться.

class BuilderChild<T> extends Builder<BuilderChild> {

    BuilderChild doSmthElse() {
        System.out.println("do smth else");
        return this;
    }
}
...
//Compile error, because doSmth() 
//returns Builder instead of BuilderChild.
new BuilderChild().doSmth().doSmthElse(); 

Может кто-нибудь объяснить, почему doSmth() начал возвращать Builder после того, как я обобщил BuilderChild? Есть ли способы исправить это?

Ответы [ 2 ]

5 голосов
/ 17 декабря 2010

Проблема в том, что вы используете BuilderChild в качестве необработанного типа.

Это означает, что он имеет аргументы типа, но вы указываете его без предоставления каких-либо параметров типа.

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

Если вы напишите это вместо:

new BuilderChild<Object>().doSmth().doSmthElse();

затем компилируется.

Кроме того, doSmthElse следует указывать как BuilderChild<T> doSmthElse().

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

0 голосов
/ 17 декабря 2010

Я предлагаю сделать что-то вроде:

abstract class Builder<T extends Builder> {

    protected T getThis();

    @SuppressWarnings("unchecked")
    T doSmth() {
        System.out.println("do smth");
        return getThis();
    }
}

class BuilderChild extends Builder<BuilderChild> {
    protected T getThis() { return this; }
    [...]

Хотя клиентский код, вероятно, лучше сделать не универсальным для разработчика.

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