如果没有强制转换,则无法将通用父对象作为子项返回

时间:2017-06-12 18:47:58

标签: java design-patterns

这个问题可能类似cast the Parent object to Child object in C#,但它与C#有关,我对Java有疑问。

我的目标也是建立一个通用的建设者。通用构建器应该只构建抽象对象的各个部分,并且子节点都管理抽象类的可行实现。

abstract class GenericBuilder<B extends GenericBuilder>
{
     //lots of build methods
     public B lastBuildingMethodInTheChain(Object someValue)
     {
          //assignment
          return this;//<-- is not allowed!
     }
}

但是当我投下演员时:return (B) this;这很好。 演员是我想要防止的,但这也限制了儿童建造者使用他们的特殊方法。 最后一件事是有道理的,因为Generic类型只在运行时才知道,但我不知道如何编写它以便在编译时工作。

谢谢!

3 个答案:

答案 0 :(得分:2)

您可以在various Guava builder methods中看到类型安全渐进缩小模式(我可能刚刚编写的名称)的示例。最后,演员阵容是必要的,但你可以合理地隐藏它:

@SuppressWarnings("unchecked")
private <B1 extends B> GenericBuilder<B1> me() {
  return (GenericBuilder<B1>) this;
}

像这样使用:

public B lastBuildingMethodInTheChain(Object someValue) {
  B self = me();
  self.assignWhatever = someValue;
  return me;
}

(我不是100%肯定这会完全正常,因为你已经有了额外的怪异,将对象作为自身的子类参数化。)

以下是一些类似的例子:

请注意使用避免演员的getThis()方法。

答案 1 :(得分:1)

这没有任何意义。 这个是一个GenericBuilder,B扩展了GenericBuilder,那么你将如何返回 this (因为GenericBuilder不会扩展自己(重复)

答案 2 :(得分:1)

声明GenericBuilder的正确方法是使用f-bound type

abstract class GenericBuilder<B extends GenericBuilder<B>> {

    public B lastBuildingMethodInTheChain(Object someValue) {
        // assignment
        return (B) this;
    }
}

您无法避免强制转换,因为编译器需要知道此泛型构建器实际上是泛型类型参数的具体构建器。

您可以按如下方式扩展通用构建器:

public class ConcreteBuilder1 extends GenericBuilder<ConcreteBuilder1> {

}

假设演员是安全的是合理的。演员失败的唯一方法是宣布即:。

public class ConcreteBuilder2 extends GenericBuilder<ConcreteBuilder3> {

}

但你为什么要这样做?