我想强迫一个对象无法向下投射,并且想知道正确的方法是什么。 用例是我有一个已检查的规则列表以及将生成失败规则列表的内容。失败的规则是规则的子类。但是倾向于像 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){
..
答案 0 :(得分:2)
这可能是您的继承层次结构设计不当的症状。您试图通过继承引入属性的可变性(如果Rule
是FailedRule
的实例,则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());
...