本文介绍了Java:构建器模式,继承和泛型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想通过继承实现Builder模式。因此,我有以下4类:一个抽象类(ClassA),ClassB,ClassC。 TestTest类用于查看所有工作原理:

I want to implement Builder Pattern with inheritance. So I have 4 following classes: one abstract class (ClassA), ClassB, ClassC. TestTest class is used to see how all this works:

public abstract class ClassA {

    private String aString;

    public String getaString() {
        return aString;
    }

    public abstract class ClassABuilder<T extends ClassABuilder>{

        public T setaString(String str) {
            ClassA.this.aString = str;
            return (T)this;
        }

        public abstract ClassA build();

    }
}

public class ClassB extends ClassA{

    private String bString;

    public String getbString() {
        return bString;
    }

    public class ClassBBuilder<T extends ClassBBuilder> extends ClassA.ClassABuilder<T>{

        public T setbString(String str) {
            ClassB.this.bString = str;
            return (T)this;
        }

        @Override
        public ClassB build(){
            return ClassB.this;
        }
    }
}

public class ClassC extends ClassB{

    private String cString;

    public String getcString() {
        return cString;
    }

    public static ClassCBuilder<ClassCBuilder> newBuilder(){
        return new ClassC().new ClassCBuilder();
    }

    public class ClassCBuilder<T extends ClassCBuilder> extends ClassB.ClassBBuilder<T>{

        public T setcString(String str) {
            ClassC.this.cString = str;
            return (T)this;
        }

        @Override
        public ClassC build(){
            return ClassC.this;
        }
    }
}

public class TestTest {

    public static void main(String[] args) {
        // TODO code application logic here
        ClassC C=ClassC.newBuilder()
                .setaString(null)
                .setbString(null)
                .setcString(null) //LINE XXX
                .build();
    }
}

问题是在XXX线的TestTest,我得到了找不到符号 setcString。我该怎么办?

The problem is that at TestTest at LINE XXX I get can't find symbol "setcString". What do I do wrong?

推荐答案

让我们沿着层次结构进行跟踪:

Let's track it down along the hierarchy:

首先考虑此签名:

class ClassABuilder<T extends ClassABuilder>

调用 setaString(null)时返回的 T 将是扩展 ClassABuilder 的对象。编译器知道这是 ClassBBuilder ,因此将允许您调用 setbString(null)

When you call setaString(null) the returned T will be an object that extends ClassABuilder. The compiler knows that this is a ClassBBuilder and thus will allow you to call setbString(null).

但是,由于定义指出 T 需要扩展 raw ClassBBuilder 只会丢失有关 ClassBBuilder 泛型类型的任何信息。因此,编译器仅知道 T ClassBBuilder ,而不是实际上是 ClassCBuilder 扩展了 ClassBBuilder< ClassCBuilder> ,因此不知道 setcString()

However, since the definition states T is required to extend a raw ClassBBuilder only any information on ClassBBuilder's generic types will be lost. Thus the compiler only knows that T is a ClassBBuilder but not that it's actually a ClassCBuilder which extends ClassBBuilder<ClassCBuilder> and hence doesn't know about setcString() on the returned type.

如前所述,使用 T扩展ClassABuilder< T> 可以解决此问题。编译器知道还有另一种通用类型要沿层次结构传递。

As has already been mentioned, using T extends ClassABuilder<T> will fix that since now the compiler knows there's another generic type to be passed down the hierarchy.

newBuilder()然后看起来像

public static ClassCBuilder<?> newBuilder(){
    //you have too create a raw type here so you'll have to ignore/suppress/live with the warning
    return (new ClassC().new ClassCBuilder());
}

这篇关于Java:构建器模式,继承和泛型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-22 16:48