Перезаписать переменную или использовать силу? - PullRequest
0 голосов
/ 07 октября 2009

Я хочу заставить класс определить определенную переменную из класса, который он реализует. например,

class Fruit{
     String name; // Cause each fruit has a name
}

//Apple wants to get an error if it does not use the name variable
class Apple implements Fruit {
     String name = "Apple";
}

Есть ли способ сделать это? Так же, как java.io.Serializable это делает?

Ответы [ 3 ]

11 голосов
/ 07 октября 2009

Я полагаю, что самый простой способ - использовать конструктор.

class Fruit{
     private final String name; 
     public Fruit(String name){ 
         if (/* name has an incorrect value, is null or whatever */) 
             throw new IllegalArgumentException("name");
         this.name = name; 
     }
}

//Apple wants to get an error if it does not use the name variable
class Apple extends Fruit {
     public Apple(){ super("Apple"); }
}

Теперь невозможно создать подкласс Fruit, который не передает имя конструктору Fruit. Делая поле final, вы также получаете дополнительный бонус, который, как только для поля было установлено правильное значение, подклассы не могут помещать фиктивные вещи туда (за исключением использования отражения и т. Д., Но тогда все ставки отключены).

Редактировать: Кроме того, как отмечают более внимательные люди, вы не implement классы, вы extend их. Для интерфейсов (которые вы делаете implement) вы не можете принудительно принудительно возвращать нормальные значения из методов (не простым способом - я полагаю, вы могли бы использовать AOP для проверки возвращаемых значений и броска IllegalStateException при возврате фиктивных значений).

3 голосов
/ 07 октября 2009

Вы не можете переопределить переменные в Java. Просто используйте интерфейс с сеттерами / геттерами или конструктором из gustafc. Вот быстрый и грязный пример:

interface Fruit {
  String getName();
  void setName(String name);
}

class Apple implements Fruit {
  private String myName="";

  public void setName(String name) { myName=name;}
  public String getName() { return myName;}
}

Лично я предпочитаю вариант конструктора, так что вещи не будут нулевыми.

1 голос
/ 19 сентября 2015

Первый вызов в конструкторе подкласса - это вызов конструктора суперкласса (требуется, добавляется компилятором при необходимости). Таким образом, когда нужное значение должно быть рассчитано в конструкторе подкласса, «стратегия конструктора» невозможна. В таком случае может быть использована стратегия ниже:

Объявите метод abstracct в суперклассе, возвращая требуемое значение, например:

protected abstract String getValue();

В суперклассе везде, где вам нужно значение, используйте метод getValue().

В подклассе сохраните значение как личное поле, например:

private String value;

В подклассе инициализируйте / установите значение (например, в конструкторе) и реализуйте абстрактный метод (обязательно, иначе класс не компилируется):

@Override
protected String getValue() {
   return value;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...