繁体   English   中英

一般行为

[英]Generic behaviour

(对不起,双关语)

假设有人想定义一个通用生成器,如下所示:

public abstract class GenericBuilder<T extends Product> {
    int x;
    int y;

    <K extends GenericBuilder<T>> K setX(int x) {
        this.x = x;
        return (K)this;
    }

    <K extends GenericBuilder<T>> K  setY(int y) {
        this.y = y;
        return (K) this;
    }

    abstract T build();
}

abstract class Product {
    int x;
    int y;
}

class ConcreteProduct extends Product {
    int z;
}

class ConcreteBuilder extends GenericBuilder<ConcreteProduct>{
    int z;

    <K extends GenericBuilder<ConcreteProduct>> K  setZ(int z) {
        this.z = z;
        return (K) this;
    }

    @Override
    ConcreteProduct build() {
        ConcreteProduct cp = new ConcreteProduct();
        cp.x = x;
        cp.y = y;
        cp.z = z;
        return cp;
    }

    public static void main(String[] args) {
        new ConcreteBuilder().setX(1).setY(2).setZ(3);
    }
}

调用ConcreteBuilder.setZ()时,编译期间将失败。

这是为什么? 是否应删除? 还是说泛型不携带有关其泛型参数的信息?

编辑:

任何想法如何避免在以下情况中使用第二个通用参数:

public class ConcreteBuilder extends GenericBuilder<ConcreteProduct, ConcreteBuilder>

即<...,ConcreteBuilder>,这似乎有点笨拙? 我想这是不可能的。 是否有其他语言(可能是C#?)允许这样做?

以这种方式破坏代码,您将了解您的类GenericBuilder<ConcreteProduct>没有定义任何setZ()方法。

    GenericBuilder<ConcreteProduct> setY = new ConcreteBuilder().setX(1).setY(2);
    setY.setZ(3);

在你GenericBuilder你的函数返回一个GenericBuilder时不指定函数的类型参数。 在您的主函数中,对setX的调用将返回GenericBuilder ,您将丢失实际上正在使用ConcreteBuilder 要成功进行调用,您必须为设置器指定通用参数:

new ConcreteBuilder().<ConcreteBuilder>setX(1).<ConcreteBuilder>setY(2).setZ(3);

另类

您可以向GenericBuilder添加第二个类型参数:

public abstract class GenericBuilder<T extends Product, K extends GenericBuilder<T, K>> {
    int x;
    int y;

    K setX(int x) {
        this.x = x;
        return (K)this;
    }

    K  setY(int y) {
        this.y = y;
        return (K) this;
    }

    abstract T build();
}

并将ConcreteBuilder更改为:

public class ConcreteBuilder extends GenericBuilder<ConcreteProduct, ConcreteBuilder> {
    int z;

    ConcreteBuilder setZ(int z) {
        this.z = z;
        return this;
    }

    @Override
    public ConcreteProduct build() {
        ConcreteProduct cp = new ConcreteProduct();
        cp.x = x;
        cp.y = y;
        cp.z = z;
        return cp;
    }

    public static void main(String[] args) {
        new ConcreteBuilder().setX(1).setY(2).setZ(3);
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM