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

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

问题描述:

我有价值对象/豆类(只包含成员,无逻辑):Java =什么是向下转换的替代品/解决方案?

public class Parent { 
String first; 
String second; 
} 

一些处理逻辑返回“父”。然后我做一些进一步的处理,并要添加furtehr领域:

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

的问题是,我不能垂头丧气从ParentParentAddedMembers

ParentAddedMembers parentAddedMembers = (ParentAddedMembers) parent; 

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

什么是正确的解决方案,如果我不想手动复制所有字段(我可以写一个复制方法,将父成员复制到新创建的ParentAddedMembers中,但这不适用于私人字段。如果我在父项中添加/删除成员,很容易中断...)

这是什么对比解决方案?

非常感谢!

马库斯

更新: 我想才达到的。我有第三方库返回一些对象父(来自搜索结果),但我需要添加更多的字段(元数据)。如所描述的向下转换将很容易地解决问题,但不起作用。我也不能改变父母,因为它来自第三方库。

+0

你为什么不试图沮丧工作?你得到的错误是什么?你是怎么声明“父母”的?因为我不明白为什么它不应该工作,不管汉堡包和芝士汉堡;-) – 2011-06-07 08:52:08

+3

汉堡包是一个汉堡包吗? – Kevin 2011-06-07 08:52:12

+1

只要想一想。一切都是对象,但是你不能把苹果当作汽车,所以你不能把所有东西都贬低为一切。你试图建模的真正问题是什么? – Kaj 2011-06-07 08:52:37

(从我在这种情况下来看这将是合法的,向下转换时未分配,新字段将只需持有空值。但似乎Java不允许这一点)。

时才有意义直观,因为在ParentParentAddedMembers领域对领域相同的名称。你说你自己有一个复制构造函数由于修改了字段而容易出错。这种铸造能力会不会太?(如果将Parent.first更改为Parent.param1,会发生什么情况。)

底线是Java不允许这样做,因为它在其他情况下没有意义。你不能投VehicleCar。 (该Vehicle对象可以是Bike。)

什么是这个corret溶液?

  • 一种选择是简单地做

    public class Parent { 
        String first; 
        String second; 
    
        boolean extended; 
        String third; 
        String fourth; 
    } 
    
  • ,或者去你解释的路线,做一个拷贝构造函数

  • 你也可以使用反射来解决它。然后,您将能够遍历Parent的所有字段,并根据字段名称分配ParentAddedMembers的字段。 (但使用反射表明一些代码味道其实。)

+0

非常感谢。你有一些有趣的新想法如何解决它。 – 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 
} 
+1

正确的解决方案 - 如果您为示例类添加初始化代码将会更加清晰 – 2011-06-07 08:55:50

+0

他明确表示他希望避免手动复制。 – 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

+0

每当你看到自己使用'instanceof',考虑多态。这就是我在这里建议的,http://*.com/questions/6262780/java-what-are-alternatives-solutions-to-downcasting/6262808#6262808 – 2011-06-07 09:50:05

+0

“父”是*不是* ParentAddedMembers的一个实例'。这只是一个“家长”。它大概编译,但在运行时抛出ClassCastException。 – aioobe 2011-06-07 09:58:06

+0

@aioobe,啊......然后,在OP的情况下,这是不可能的,通过铸造。 – 2011-06-07 10:01:02