3

我想对一个不能被向下投射的对象强制进行向下转换,并且想知道正确的方法是什么。用例是我有一个检查的规则列表以及生成失败规则列表的内容。失败的规则是规则的子类。但是像
FailedRule failedRule = (FailedRule) rule;

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

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

我的 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){
  ..
4

6 回答 6

2

这可能是您的继承层次结构设计薄弱的症状。您正在尝试通过继承引入属性的可变性(Rule如果它是 instance-of ,则 a 已“失败” FailedRule)。继承对于那种事情来说并不是很好。

我会说您应该使用组合(FailedRule 有一个规则作为源)或者failed应该是Rule.

于 2010-12-03T16:03:23.680 回答
2

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

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

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

于 2010-12-03T17:14:11.223 回答
1

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

编辑: 失败听起来很像一种状态,而不是规则的变体。如果是这样的Rule.isFailed()话也将是首选。如果存在确实不会失败的规则,我们可以将其建模为:

           Rule
         /      \
         |       \
    FailableRule  RuleC
     /     |   
 RuleA    RuleB

嗯......一个失败的规则实际上是一个错误的规则吗?Gaawgh...语言学。

于 2010-12-03T16:00:29.533 回答
0

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

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

私人无效copyFromRule(规则其他规则){
  this.setRuleCode(otherRule.getRuleCode());
  this.setType(otherRule.getType());
  ...
}

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

另一点是要知道你是在打电话super.setRuleCode还是this.setRuleCode。显然,这两件事根据 if FailedRuleredefines做不同的事情setRuleCode

于 2010-12-03T15:59:40.230 回答
0

你不能像这样将一个类转换为一个子类。它没有任何意义,因为它没有来自子类的任何方法或变量。你做对的方式。

于 2010-12-03T16:01:32.417 回答
0

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

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());
   ...
于 2010-12-03T16:17:42.983 回答