Java中的强制向下转换

时间:2010-12-03 15:56:32

标签: java class object casting downcast

我想强迫一个对象无法向下投射,并且想知道正确的方法是什么。 用例是我有一个已检查的规则列表以及将生成失败规则列表的内容。失败的规则是规则的子类。但是倾向于像      FailedRule failedRule =(FailedRule)规则;

将失败,因为规则对象不是FailedRule的实例

为了解决这个问题,我实例化了一个克隆;
     FailedRule failedRule = new FailedRule(rule);

我的FailedRule类看起来像这样

public class FailedRule extends Rule{

/* 
 *force a down cast from Rule to FailedRule through cloning
*/
public FailedRule (Rule upcast){
   super.setRuleCode( upcast.getRuleCode());
   super.setType(upcast.getType());
   ..

有更简单的方法吗? 为了回答自己,设计存在缺陷,代码应为:

public class FailedRule{
  private Rule rule;
  ..
  public setRule(Rule rule){
  ..

6 个答案:

答案 0 :(得分:2)

这可能是您的继承层次结构设计不当的症状。您试图通过继承引入属性的可变性(如果RuleFailedRule的实例,则failed已“失败”。继承对于那种事情并不是很好。

我想你应该使用合成(FailedRule有一个规则作为源)或Rule应该是{{1}}实例的布尔属性。

答案 1 :(得分:2)

使用将任何规则转换为FailedRule的方法:

public static FailedRule asFailedRule(Rule rule){
    return (rule instanceof FailedRule)
    ? (FailedRule) rule
    : new FailedRule(rule)
}

(如果规则已经是FailedRule,则转换并返回,否则使用它来构建FailedRule

答案 2 :(得分:1)

你所拥有的是一个合理的解决方案。如果任何规则可能是失败的规则,那么将其建模为Rule.isFailed()可能更合适。

编辑: 失败听起来非常像一个州,而不是规则的变体。如果是这种情况,Rule.isFailed()也会更喜欢。如果有些规则确实没有失败,我们可以将其建模为:

           Rule
         /      \
         |       \
    FailableRule  RuleC
     /     |   
 RuleA    RuleB

嗯... failable 规则实际上是易错规则?高文...语言学。

答案 3 :(得分:0)

没有更简单的方法。你这样做是正确的。

很多时候,我会编写一个私有方法,如下所示:

private void copyFromRule(Rule otherRule) {
  this.setRuleCode(otherRule.getRuleCode());
  this.setType(otherRule.getType());
  ...
}

这样,我可以在这样的构造函数中调用它,如果我需要定义一个,也可以在clone()方法中调用它。

另一点是要知道您是在呼叫super.setRuleCode还是this.setRuleCode。显然,这两件事情会有所不同,具体取决于FailedRule是否重新定义setRuleCode

答案 4 :(得分:0)

您不能将类转换为类似的子类。它没有意义,因为它没有子类中的任何方法或变量。你做得对的方式。

答案 5 :(得分:0)

你这样做是正确的。我必须添加的唯一注释是将复制代码移动到规则本身。

public class FailedRule extends Rule{

/* 
 *force a down cast from Rule to FailedRule through cloning
*/
public FailedRule (Rule upcast){
   super(upcast);
   //init FailedRule fields to defaults
}
}

public class Rule {

publiic Rule(Rule ruleToCopy) {
   //or even use the fields themselves. 
   this.setRuleCode( ruleToCopy.getRuleCode());
   this.setType(ruleToCopy.getType());
   ...