我有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。
答案 0 :(得分:4)
(从我的观点来看,在这种情况下它是合法的,当向下转换未分配的新字段时只会保留空值。但似乎java不允许这样做。) < / em>的
这只是直观的,因为Parent
和ParentAddedMembers
中的字段具有相同的字段名称。你自己说,由于对字段的修改,拥有一个复制构造函数是容易出错的。这样的铸造能力不是吗? (如果您将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更改,使用反射,动态代理等)最好创建一个包装类,其中包含最初返回的第三方对象和您的加号字段。