【问题标题】:Generic parent object cannot be returned as child without cast没有强制转换,通用父对象不能作为子对象返回
【发布时间】:2017-06-12 18:47:57
【问题描述】:

这个问题可能类似于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 类型仅在运行时才知道,但我不知道如何编写它以便在编译时工作。

谢谢!

【问题讨论】:

  • 所有这些答案都让我想到了一个新问题:我不能“拥有多个孩子”。我不确定是否必须编辑此问题或提出新问题。
  • 我提出了一个新问题来解决我的真正问题。 stackoverflow.com/questions/44527022/…这个问题我会再来一次,这样对别人会更有用。

标签: java design-patterns


【解决方案1】:

您可以在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() 方法的使用,它可以避免强制转换。

【讨论】:

  • 在您发布的一些文章之后,我得到了一个不强制执行参数顺序或强制执行的构建器。我会将这个添加到问题中。
【解决方案2】:

声明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> {

}

但是你为什么要这样做呢?

【讨论】:

  • 我猜你的答案最接近我所寻找的。但是我的问题没有解决。
  • @RabbitBones22 为什么你的问题没有解决?现在通用构建器的方法返回具体构建器的类型,允许您链接方法。
  • 我可能做错了什么,因为我无法在 abstractBuilder 之后动态链接子构建器。 Java 认为返回了一个对象,或者我必须对接口返回进行硬编码。
  • @RabbitBones22 你的问题现在解决了吗?如果您需要帮助,请告诉我
  • 不,而是我创建了一个新问题(请参阅我在答案下的评论)。虽然这个特定的部分问题已经解决了。
【解决方案3】:

这毫无意义。 this 是一个 GenericBuilder,而 B 扩展了 GenericBuilder,那么你将如何返回 this (因为 GenericBuilder 不扩展自身(重言式)

【讨论】:

  • 我忘了说通用构建器是抽象的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多