Могу ли я добавить функцию в перечисления в Java? - PullRequest
58 голосов
/ 16 марта 2010

У меня есть enum, который выглядит как

public enum Animal {
  ELEPHANT,
  GIRAFFE,
  TURTLE,
  SNAKE,
  FROG
}

и я хочу сделать что-то вроде

Animal frog = Animal.FROG;
Animal snake = Animal.SNAKE;

boolean isFrogAmphibian = frog.isAmphibian(); //true
boolean isSnakeAmphibian = snake.isAmphibian(); //false

boolean isFrogReptile = frog.isReptile(); //false
boolean isSnakeReptile = snake.isReptile(); //true

boolean isFrogMammal = frog.isMammal(); //false
boolean isSnakeMammal = snake.isMammal(); //false

Я упростил пример для дидактических целей, но это было бы очень полезно для моего примера из реальной жизни. Могу ли я сделать это на Java?

Ответы [ 3 ]

77 голосов
/ 16 марта 2010

Да. Enum - это класс в Java:

public enum Animal 
{
  ELEPHANT(true),
  GIRAFFE(true),
  TURTLE(false),
  SNAKE(false),
  FROG(false);

  private final boolean mammal; 
  private Animal(final boolean mammal) { this.mammal = mammal; }
  public boolean isMammal() { return this.mammal; }
}

, но в вашем случае для реальной системы я бы также сделал это Enum, поскольку существует фиксированный набор типов животных.

public enum Type
{
  AMPHIBIAN,
  MAMMAL,
  REPTILE,
  BIRD
}

public enum Animal 
{
  ELEPHANT(Type.MAMMAL),
  GIRAFFE(Type.MAMMAL),
  TURTLE(Type.REPTILE),
  SNAKE(Type.REPTILE),
  FROG(Type.AMPHIBIAN);

  private final Type type; 
  private Animal(final Type type) { this.type = type; }
  public boolean isMammal() { return this.type == Type.MAMMAL; }
  public boolean isAmphibian() { return this.type == Type.AMPHIBIAN; }
  public boolean isReptile() { return this.type == Type.REPTILE; }
  // etc...
}

Также обратите внимание, что важно также сделать любую переменную экземпляра final.

15 голосов
/ 16 марта 2010

Да, вы можете. Это будет выглядеть так:

public enum Animal {
  ELEPHANT(false),
  GIRAFFE(false),
  TURTLE(false),
  SNAKE(false),
  FROG(true);

  private final boolean isAmphibian;

  Animal(boolean isAmphibian) {
    this.isAmphibian = isAmphibian;
  }

  public boolean isAmphibian() {
    return this.isAmphibian;
  }
}

Тогда вы бы назвали это как:

Animal.ELEPHANT.isAmphibian()

2 голосов
/ 22 мая 2018

Помимо использования описанных выше методов, которые добавляют поле к перечисляемому типу, вы также можете использовать подход, основанный только на методах, и полиморфизм. Это больше "ООП стиль", но я бы не сказал, что это обязательно лучше.

К сожалению, вам нужно определить интерфейс:

public interface AnimalTraits {
    default boolean isAmphibian()   { return false; };
    default boolean isReptile()     { return false; };
    default boolean isMammal()      { return false; };
}

Но тогда вы сможете реализовать интерфейс в каждом из ваших элементов перечисления:

public enum Animal implements AnimalTraits {

     ELEPHANT   { @Override public boolean isMammal()    { return true; } },
     GIRAFFE    { @Override public boolean isMammal()    { return true; } },
     TURTLE     { @Override public boolean isReptile()   { return true; } },
     SNAKE      { @Override public boolean isReptile()   { return true; } },
     FROG       { @Override public boolean isAmphibian() { return true; } }
}

Обратите внимание, что я использую реализации по умолчанию в интерфейсе, чтобы сократить количество набираемого текста в перечислении.

Относительно необходимости интерфейса: я пытался добавить методы в интерфейс, поскольку абстрактные методы в верхней части enum и Eclipse, казалось, позволяли это, и настаивал на реализации в элементах enum, но затем не смог скомпилировать их должным образом. Похоже, что это возможно без интерфейса, но, возможно, это еще не реализовано в компиляторе.

Примечание: требуется Java 8 или выше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...