2010-12-03 74 views
3

我想迫使某个对象不高兴,但不知道什么是正确的方法。 用例是我有一个检查规则的列表,以及将生成失败规则列表的内容。失败的规则是规则的子类。但向下倾斜如
FailedRule failedRule =(FailedRule)规则;Java中的强制向下转换

将失败,因为该规则的对象不是一个instanceof 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){ 
    .. 
+0

我想知道你最终不得不对一个不能被击倒的对象强制下注。向我们解释你真正想做的事情。 – 2010-12-03 16:01:18

+0

虽然我做了:-)。我遍历一系列规则并返回失败的规则列表。检查过程为每个规则返回相当数量的信息为什么,何时以及如何失败。马克的回答是正确的,我的设计是错误的,我不能说失败的规则是'规则'。它有一条规则。我编辑了这个问题,因为我不能在这些注释中放置代码 – Meindert 2010-12-06 08:16:38

回答

2

这可能是您的继承层次设计较差的一个症状。您试图通过继承来引入属性的可变性(如果Rule的实例为FailedRule,则它具有“失败”)。继承对于这种事情并不是很好。

我会说你应该使用组合(一个FailedRule有一个规则作为源)或failed应该是Rule的一个实例的布尔属性。

0

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

很多时候,我会写一个私有方法,这样的事情:

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

这样一来,我可以把它在这样的构造,以及呈clone()方法,如果我需要定义一。

另一点是要知道你是否打电话super.setRuleCodethis.setRuleCode。显然,这两件事情做不同的事情取决于FailedRule重新定义setRuleCode

+0

-1,问题在于设计。看Mark Peters的回答。 – 2010-12-04 18:00:44

1

你看起来像一个合理的解决方案。如果任何规则可能是失败的规则,那么将其作为Rule.isFailed()进行建模可能更合适。

编辑:失败听起来很像一个国家,而不是一个规则的变种。如果是这样的话,Rule.isFailed()也会更喜欢。如果有真的没有失败的规则,我们可以模型为:

  Rule 
     / \ 
     |  \ 
    FailableRule RuleC 
    / | 
RuleA RuleB 

嗯...是failable规则实际上是一个会犯错误规则? Gaawgh ...语言学。

+0

这是一个好主意,即使该方法只在`Rule`中包含`return false;`并且在`FailedRule`中被覆盖为`return true;`。 – 2010-12-03 16:05:27

+0

其实只是想到了另外一件事。 *失败*听起来很像一个规则的状态,而不是一个规则的变体。如果是这样的话,`FailedRule`不是很好哦。 – 2010-12-03 17:02:18

0

您不能将类转换为这样的子类。它没有任何意义,因为它没有任何子类的方法或变量。你做对的方式是正确的。

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()); 
    ... 
2

使用该功能可将任何规则的FailedRule的方法:

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

(如果该规则已经是FailedRule,演员和返回它,否则用它来构建一个FailedRule