枚举可以有抽象方法吗?

时间:2011-09-14 09:10:06

标签: java enums abstract

枚举可以有抽象方法吗?如果是这样,有什么用,并给出一个场景来说明这种用法。

4 个答案:

答案 0 :(得分:59)

是的,但您可能更喜欢实现接口的枚举Look here。我认为看起来好多了。这是抽象方法的示例:

public enum Animal {
    CAT {
        public String makeNoise() { return "MEOW!"; }
    },
    DOG {
        public String makeNoise() { return "WOOF!"; }
    };

    public abstract String makeNoise();
}

答案 1 :(得分:18)

是的,您可以在abstract声明中定义enum方法当且仅当所有枚举值都包含具有这些方法实现的自定义类主体时(即没有具体的枚举)价值可能缺乏实施。)

public enum Foo {
  BAR {
    public void frobnicate() {
      // do BAR stuff
    }
  },
  BAZ {
    public void frobnicate() {
      // do BAZ stuff
    }
  };

  public abstract void frobnicate();
}

答案 2 :(得分:0)

是的,枚举可以包含抽象方法-如果每个枚举常量都有自己的实现,则可以使用此方法。 (或者您可以省略使用抽象方法,而对每个枚举常量Enum with customized value in Java使用自定义值)

例如(特定于常量的方法实现

enum TrafficSignal {

    RED{
        @Override
        public void action(){
            System.out.println("STOP");
        }
    }, 
    GREEN{
        @Override
        public void action(){
            System.out.println("GO");
        }
    }, 
    ORANGE{
        @Override
        public void action(){
            System.out.println("SLOW DOWN");
        }
    };


    public abstract void action();
}

如果此方法对于所有枚举常量均通用,则请考虑使用interface。 (Java枚举隐式扩展了java.lang.Enum泛型类,因此您的枚举类型不能扩展另一个类(因为Java不支持多重继承)但可以实现接口)

interface ColorInterface{
    void inLowerCase();
}

enum Color implements ColorInterface{

    RED, GREEN, ORANGE;

    @Override
    public void inLowerCase(){
        System.out.println(this.toString().toLowerCase());
    }
}

用法:

public class TestEnums{

     public static void main(String []args){
        TrafficSignal signal = TrafficSignal.RED;
        signal.action();

        ColorInterface color = Color.RED;
        color.inLowerCase();
     }
}

出局:

STOP
red

如果某些(但不是全部)枚举常量共享常见行为,请考虑策略枚举模式。 [有效的Java-Joshua Bloch-第三版。第166页]

答案 3 :(得分:0)

就像@lukastymo的答案一样,可以在枚举中实现抽象方法,并且在枚举中添加方法时最好实现接口。

在Java 8及更高版本中,可以使用lambda在枚举中实现较小代码的方法。通过公开运行给定lambda的公共方法,可以在枚举之外执行这些lambda。

public enum ScheduleRepeat {
  DAILY(date -> date.plusDays(1)),
  WEEKLY(date -> date.plusWeeks(1)),
  MONTHLY(date -> date.plusMonths(1)),
  QUARTERLY(date -> date.plusMonths(3)),
  BIANNUALLY(date -> date.plusMonths(6)),
  ANNUALLY(date -> date.plusYears(1)),
  ;

  private final Function<LocalDate, LocalDate> nextDateFunction; // or UnaryOperator<LocalDate>

  ScheduleRepeat(Function<LocalDate, LocalDate> nextDateFunction) {
    this.nextDateFunction = nextDateFunction;
  }

  public LocalDate calculateNextDate(LocalDate dateFrom) {
    return nextDateFunction.apply(dateFrom);
  }
}

那么枚举可以像这样使用:

LocalDate today = LocalDate.of(2019, 9, 18); // 2019 Sep 18
ScheduleRepeat.DAILY.calculateNextDate(today); // 2019-09-19
ScheduleRepeat.MONTHLY.calculateNextDate(today); // 2019-10-19

这不是从枚举本身或从接口完全实现抽象方法,但我认为这种使用lambda添加方法的方法看起来很干净。