Принудительный Даункинг в Java - PullRequest
3 голосов
/ 03 декабря 2010

Я хочу навести объект на объект, который нельзя отбрасывать, и мне было интересно, какой будет правильный подход.Сценарий использования: у меня есть список проверенных правил и список сгенерированных правил.Неудачное правило является подклассом правила.Но уныние, как
FailedRule failedRule = (FailedRule) rule;

завершится ошибкой, поскольку объект правила не является экземпляром FailedRule

Чтобы обойти это, я создаюclone;
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 ]

2 голосов
/ 03 декабря 2010

Используйте метод, который преобразует любое правило в FailedRule:

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

(Если правило уже является FailedRule, приведите и верните его, в противном случае используйте его для создания FailedRule)

2 голосов
/ 03 декабря 2010

Это, вероятно, признак того, что ваша иерархия наследования слабо разработана. Вы пытаетесь ввести изменчивость атрибутов посредством наследования (Rule "не удалось", если это экземпляр FailedRule). Наследование не очень хорошо для такого рода вещей.

Я бы сказал, что вы должны либо использовать состав (FailedRule имеет правило в качестве источника), либо failed должен быть логическим атрибутом экземпляра Rule.

1 голос
/ 03 декабря 2010

То, что у вас есть, выглядит разумным решением.Если какое-либо правило может быть правилом с ошибкой, может быть более подходящим моделировать его как Rule.isFailed().

Редактировать: Failed звучит очень похоже на состояние, не вариант правила.Если это так, то Rule.isFailed() также будет предпочтительным.Если есть правила, которые действительно не терпят неудачу, мы могли бы смоделировать это как:

           Rule
         /      \
         |       \
    FailableRule  RuleC
     /     |   
 RuleA    RuleB

Хмм ... правило неудачное на самом деле ошибочное правило?Gaawgh ... лингвистика.

0 голосов
/ 03 декабря 2010

То, как вы делаете это правильно.Единственный комментарий, который я должен добавить, - переместить код копирования в само правило.

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());
   ...
0 голосов
/ 03 декабря 2010

Вы не можете привести класс к подклассу, подобному этому.Это не имеет смысла, поскольку в нем не было бы методов или переменных из подкласса.То, как вы делаете это правильно.

0 голосов
/ 03 декабря 2010

Нет более простого пути. Вы делаете это правильно.

Много раз я напишу приватный метод, что-то вроде этого:

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

Таким образом, я могу вызвать его в таком конструкторе, а также в методе clone(), если мне нужно определить его.

Другой момент - узнать, звоните ли вы super.setRuleCode или this.setRuleCode. Очевидно, что эти две вещи делают разные вещи в зависимости от того, переопределяет ли FailedRule setRuleCode.

...