Java =什么是向下转换的替代品/解决方案?
我有价值对象/豆类(只包含成员,无逻辑):Java =什么是向下转换的替代品/解决方案?
public class Parent {
String first;
String second;
}
一些处理逻辑返回“父”。然后我做一些进一步的处理,并要添加furtehr领域:
public class ParentAddedMembers extends Parent {
String third;
String fourth;
}
的问题是,我不能垂头丧气从Parent
到ParentAddedMembers
。
ParentAddedMembers parentAddedMembers = (ParentAddedMembers) parent;
这似乎是无效的。 (从我的观点来看,在这种情况下,当向下转换未分配的字段时,新的字段只会包含空值,但似乎java不允许这样做)。
什么是正确的解决方案,如果我不想手动复制所有字段(我可以写一个复制方法,将父成员复制到新创建的ParentAddedMembers中,但这不适用于私人字段。如果我在父项中添加/删除成员,很容易中断...)
这是什么对比解决方案?
非常感谢!
马库斯
更新: 我想才达到的。我有第三方库返回一些对象父(来自搜索结果),但我需要添加更多的字段(元数据)。如所描述的向下转换将很容易地解决问题,但不起作用。我也不能改变父母,因为它来自第三方库。
(从我在这种情况下来看这将是合法的,向下转换时未分配,新字段将只需持有空值。但似乎Java不允许这一点)。
时才有意义直观,因为在Parent
和ParentAddedMembers
领域对领域相同的名称。你说你自己有一个复制构造函数由于修改了字段而容易出错。这种铸造能力会不会太?(如果将Parent.first
更改为Parent.param1
,会发生什么情况。)
底线是Java不允许这样做,因为它在其他情况下没有意义。你不能投Vehicle
到Car
。 (该Vehicle
对象可以是Bike
。)
什么是这个corret溶液?
-
一种选择是简单地做
public class Parent { String first; String second; boolean extended; String third; String fourth; }
,或者去你解释的路线,做一个拷贝构造函数。
你也可以使用反射来解决它。然后,您将能够遍历
Parent
的所有字段,并根据字段名称分配ParentAddedMembers
的字段。 (但使用反射表明一些代码味道其实。)
非常感谢。你有一些有趣的新想法如何解决它。 – Markus 2011-06-07 19:44:43
忘掉它,并尝试了解多态以及它在这方面如何帮助你。
[一downvote后编辑]
谁downvoted我,你可能不喜欢我的措辞。但请尝试理解我说的话。它可能是模糊的,但这意味着不要这样做,而是使用多态。有一个getter()
和setter()
,使用多态并避免完全投射。
[问题更新后编辑]
然后,你应该考虑寻找到Adapter Pattern。
我不是说这是总是如此,但是这可能表明一个设计缺陷,如果你需要访问的对象作为子类型为什么它被引用为父类型。
然而,要回答你的问题,敷投在if instanceof
使用构造函数。
Parent(Parent p) {
// initalize it
}
ParentAddedMembes(Parent p) {
super(p);
// By default, fields are null
}
正确的解决方案 - 如果您为示例类添加初始化代码将会更加清晰 – 2011-06-07 08:55:50
他明确表示他希望避免手动复制。 – aioobe 2011-06-07 08:57:26
你可以写一个ParentAddedMembes构造,这样的构造将采取父对象作为参数,并与母公司的数据填充本身。
事情是这样的:
public ParentAddedMembes(Parent parent) {
// populate
}
再后来
ParentAddedMembes parentAddedMembes = new ParentAddedMembes(parent);
“问题是,我不能垂头丧气从家长到ParentAddedMembers”
的问题是,你想不沮丧。你要上溯造型:)
的东西,你可以做,当你想使用扩展的成员,检查类型,然后投:
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更改,反射,动态代理等的使用)最好创建一个包含最初返回的第三方对象AS和您的加号字段的包装类。
奇怪,因为你的代码是有效的。我的猜测是Parent
类型的变量没有保存的值是ParentAddedMembes
。
Parent parent = new ParentAddedMembes();
ParentAddedMembes pm = (ParentAddedMembes) parent;
上述代码是有效的。但是,您可以使用instanceof
关键字进行向下转换。例如
Parent parent = new ParentAddedMembes();
if (parent instanceof ParentAddedMembes)
ParentAddedMembes pm = (ParentAddedMembes) parent;
这是检查父母是否是ParentAddedMembes
。
每当你看到自己使用'instanceof',考虑多态。这就是我在这里建议的,http://*.com/questions/6262780/java-what-are-alternatives-solutions-to-downcasting/6262808#6262808 – 2011-06-07 09:50:05
“父”是*不是* ParentAddedMembers的一个实例'。这只是一个“家长”。它大概编译,但在运行时抛出ClassCastException。 – aioobe 2011-06-07 09:58:06
@aioobe,啊......然后,在OP的情况下,这是不可能的,通过铸造。 – 2011-06-07 10:01:02
你为什么不试图沮丧工作?你得到的错误是什么?你是怎么声明“父母”的?因为我不明白为什么它不应该工作,不管汉堡包和芝士汉堡;-) – 2011-06-07 08:52:08
汉堡包是一个汉堡包吗? – Kevin 2011-06-07 08:52:12
只要想一想。一切都是对象,但是你不能把苹果当作汽车,所以你不能把所有东西都贬低为一切。你试图建模的真正问题是什么? – Kaj 2011-06-07 08:52:37