在尝试扩展Java对象时如何避免向下转换

在尝试扩展Java对象时如何避免向下转换,java,oop,downcast,Java,Oop,Downcast,我从对外部API的调用中获得了几个类型为Foo的对象。在本地,我想用一些添加的信息处理这些对象,因此我有一个子类FooSon,它添加了这些额外的字段。如何将我得到的所有对象转换为新的继承类型?向下投射似乎不是一个选项,因为这些对象并不是真正的FooSon 我提出的唯一解决方案是创建一个convert函数,该函数将Foo对象作为参数,然后将所有公共/受保护的值复制到一个新的FooSon对象,然后返回该对象 缺点是: 丢失信息(私有值) 如果Foo发生变化,则必须调整转换功能 类Foo未实现复制

我从对外部API的调用中获得了几个类型为Foo的对象。在本地,我想用一些添加的信息处理这些对象,因此我有一个子类FooSon,它添加了这些额外的字段。如何将我得到的所有对象转换为新的继承类型?向下投射似乎不是一个选项,因为这些对象并不是真正的FooSon

我提出的唯一解决方案是创建一个convert函数,该函数将Foo对象作为参数,然后将所有公共/受保护的值复制到一个新的FooSon对象,然后返回该对象

缺点是:

  • 丢失信息(私有值)
  • 如果Foo发生变化,则必须调整转换功能

类Foo未实现复制构造函数或克隆运算符。我有Foo源代码,但我希望避免更改它,以保持与未来版本的兼容性。尽管如此,如果这是唯一可行的替代方案,我会更改Foo实现以获得我需要的内容。

FooSon可以在其中包含一个字段,即Foo。然后将返回值分配到该字段中。然后,您可以在Fooson中创建方法,将它们的调用委托给Foo字段,以获取您需要的来自外部Foo的信息。

也许我还没有完全理解这个问题,但是为什么您不在Fooson(组合)中像字段类型一样存储Foo而不是子类化Foo(继承)


在任何情况下,如果由于对象定义在外部库中而无法将访问控制修改为Foo类型,则无法直接访问私有字段(这正是私有字段的属性)。如果可以从getter和setters方法访问这些私有字段,那么将这些方法包装到FooSon类中。

好吧,正如您已经发现的那样,向下转换不适用于这种情况。我看到以下选项:

  • 外部库提供了一些工厂机制,您可以使用它来实例化
    FooSon
    ,而不是
    Foo

  • 收件人将
    Foo
    对象包装在
    FooSon
    对象中,可能使用delegator模式

  • 收件人通过使用以
    Foo
    为键的映射,在逻辑上将附加信息附加到
    Foo
    对象


    • 你不应该沮丧,你不能保证它会成功,而且有更好的方法来解决这个问题。 首先,您可以在另一个类中包装Foo对象,并将适当的方法调用委托回Foo对象

      我建议您花一些时间来确保理解一些基本的OO概念。
      尤其是谷歌的“组合与继承”,这似乎是一个不错的解释。

      我认为装饰模式应该在这里起作用:

      class Foo implements FooApi {...}
      
      class FooSon implements FooApi {
          private FooApi decoratedFoo;
          private String additional;
      
          public FooSon(FooApi decoratedFoo) {
              this.decoratedFoo = decoratedFoo;
          }
          ...
      }
      

      但是,只有当您的Foo对象有接口时,您才能这样做。

      只是为了说明我没有设计Foo,我不应该更改它。它在一个.jar中,我从开发人员存储库获得了源代码。更改Foo意味着转储.jar并将src合并到我自己的project.Composition中,而不是继承。我考虑过这一点,要“重新路由”所有15种Foo公共方法有点麻烦。也许这是唯一的选择……我绝对不是专家,但我确实理解继承和组合之间的区别-我想避免组合的原因是不必委托所有这些方法(你知道的,懒惰的程序员…)嘿-这看起来像是努力,但这是正确的做法。如果您使用的是一个功能强大的IDE,那么您可以实现一个模板,从而减轻一些痛苦。我使用eclipse,下面是一个模板示例,我将使用它快速地将方法调用委托给foo对象。foo.${enclosing_method}(${enclosing_method_arguments})。。。和foo.${enclosing_method}当它是一种无参数方法时,您让我搜索了一下,我发现使用Netbeans(我最喜欢的IDE),您可以使用两个鼠标图标生成所有委托方法:-)我同意这是一种装饰器模式非常适合的情况。不幸的是,正如我指出的,我无法控制Foo。