Java =什么是向下转型的替代方案/解决方案?

时间:2011-06-07 08:49:16

标签: java

我有Value-Objects / Beans(只包含成员,没有逻辑):

public class Parent {
String first;
String second;
}

某些处理逻辑返回“Parent”。然后我做了一些进一步的处理,并希望添加furtehr字段:

public class ParentAddedMembers extends Parent {
String third;
String fourth;
} 

问题是,我不能从Parent转发到ParentAddedMembers

ParentAddedMembers parentAddedMembers = (ParentAddedMembers) parent;

这似乎无效。

(从我的观点来看,在这种情况下它是合法的,当向下转换未分配的新字段时,它只会保留空值。但似乎java不允许这样做。)

如果我不想手动复制所有字段,那么正确的解决方案是什么(我可以编写一个将父成员复制到新创建的ParentAddedMembers的复制方法。但这对私有字段不起作用。此外它会破坏如果我在父母中添加/删除元素很容易...)

对此有什么相关解决方案?

非常感谢!

马库斯

更新 我想要的是。我有一个第三方库,它返回一些Objects Parent(来自搜索结果),但我需要向它添加更多字段(元数据)。如上所述,向下转换可以轻松解决问题,但不起作用。我也无法更改父级,因为它来自第三方lib。

8 个答案:

答案 0 :(得分:4)

  

(从我的观点来看,在这种情况下它是合法的,当向下转换未分配的新字段时只会保留空值。但似乎java不允许这样做。) < / em>的

这只是直观的,因为ParentParentAddedMembers中的字段具有相同的字段名称。你自己说,由于对字段的修改,拥有一个复制构造函数是容易出错的。这样的铸造能力不是吗? (如果您将Parent.first更改为Parent.param1,该怎么办。)

底线是Java不允许这样做,因为在其他情况下它没有意义。您无法将Vehicle投射到Car。 (Vehicle对象可能是Bike。)

  

有什么相关解决方案?

  • 一种选择就是简单地做

    public class Parent {
        String first;
        String second;
    
        boolean extended;
        String third;
        String fourth;
    }
    
  • 或者,按照您解释的路线并执行复制构造函数

  • 您也可以使用反射解析 。然后,您将能够循环遍历Parent的所有字段,并根据字段名称指定ParentAddedMembers的字段。 (但使用反射表明实际上有些代码味道。)

答案 1 :(得分:3)

忘记它,并尝试理解多态性以及它在这方面如何帮助你。

[在downvote之后编辑]

无论是谁投票给我,你都可能不喜欢我的措辞。但请尝试理解我说的话。它可能很模糊,但这意味着不要这样做,而是使用多态。拥有getter()setter(),使用多态并完全避免使用。

[问题更新后编辑]

然后,你应该考虑研究Adapter Pattern

答案 2 :(得分:1)

使用构造函数。

Parent(Parent p) {
// initalize it
}

ParentAddedMembes(Parent p) {
   super(p);
   // By default, fields are null
}

答案 3 :(得分:1)

您可以为ParentAddedMembes编写构造函数,以便构造函数将Parent对象作为参数并使用Parent的数据填充自身。

这样的事情:

public ParentAddedMembes(Parent parent) {
    // populate
}

然后是

ParentAddedMembes parentAddedMembes = new ParentAddedMembes(parent);

答案 4 :(得分:1)

奇怪,因为您的代码有效。我的猜测是Parent类型的变量没有保持ParentAddedMembes的值。

Parent parent = new ParentAddedMembes();
ParentAddedMembes pm = (ParentAddedMembes) parent;

以上代码有效。但是,您可以使用instanceof关键字进行向下转换。 e.g

Parent parent = new ParentAddedMembes();

if (parent instanceof ParentAddedMembes)
    ParentAddedMembes pm = (ParentAddedMembes) parent;

这是为了检查父母是否属于ParentAddedMembes

答案 5 :(得分:0)

我并不是说情况总是如此,但这可能表明存在设计缺陷,如果您需要将对象作为子类型访问,为什么它被引用为父类型。

但是,要回答您的问题,请将演员表封装在if instanceof

答案 6 :(得分:0)

“问题是,我不能从父母转发到ParentAddedMembers”

问题是,你不想DOWNcast。你想要UPcast:)

答案 7 :(得分:0)

当你想使用扩展程序的成员时,你可以做的事情是检查类型和那么强制转换:

if(variable instanceof ParentAddressMembers) {
  ParentAddressMembers pam = (ParentAddressMembers)variable;
  // you can access pam.third and pam.forth here.
} else {
 // you can't acces pam.third and pam.forth so better not to bother them.
}

在阅读更新后,我添加了以下内容:但是,扩展第三方类并不是一个好主意,因为基类可能会严重干扰您的扩展。 (基本API更改,使用反射,动态代理等)最好创建一个包装类,其中包含最初返回的第三方对象和您的加号字段。