枚举可以有抽象方法吗?

Posted

技术标签:

【中文标题】枚举可以有抽象方法吗?【英文标题】:Can an enum have abstract methods? 【发布时间】:2011-11-16 20:25:55 【问题描述】:

如果有,有什么用,并给出一个场景来说明这种用法。

【问题讨论】:

使用哪种语言?这听起来像是一个家庭作业,如果是这样,请使用家庭作业标签 JAVA。我从未使用带有抽象方法的枚举。我正在尝试了解我可以拥有这样的事情的场景。 不,您正在尝试找出您是否可以拥有这样的东西。编译器会告诉你,我不明白你为什么需要论坛。 【参考方案1】:

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

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

    public abstract String makeNoise();

【讨论】:

在多态的代码示例中总是使用 Animal =)【参考方案2】:

是的,您可以在 enum 声明中定义 abstract 方法当且仅当所有枚举值都具有自定义类主体以及这些方法的实现(即可能缺少具体的枚举值一个实现)。

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

  public abstract void frobnicate();

【讨论】:

【参考方案3】:

就像@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 添加方法的方法看起来很干净。

【讨论】:

【参考方案4】:

是的,枚举可以包含抽象方法——如果每个枚举常量都有自己的实现,则可以使用这种方法。 (或者您可以省略使用抽象方法,使用每个枚举常量 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();

如果此方法对所有枚举常量都通用,则考虑使用接口。 (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

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

【讨论】:

以上是关于枚举可以有抽象方法吗?的主要内容,如果未能解决你的问题,请参考以下文章

Java枚举抽象方法实战

java的枚举类enum,定义静态变量还可以有抽象方法,但枚举类不能被继承

枚举类+抽象方法+内部类

抽象枚举类型及其值的方法

0013JDK源码分析之枚举

Java面试题|抽象类必须要有抽象方法吗?