枚举可以有抽象方法吗?

jav*_*eek 43 java enums abstract

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

luk*_*ymo 66

是的,但您可能更喜欢实现界面的枚举,请看这里.我认为看起来好多了.这是抽象方法的示例:

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

    public abstract String makeNoise();
}
Run Code Online (Sandbox Code Playgroud)

  • 始终在多态的代码示例中使用Animal =) (2认同)

Joa*_*uer 18

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

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

  public abstract void frobnicate();
}
Run Code Online (Sandbox Code Playgroud)


Mus*_*usa 7

是的,枚举可以包含抽象方法 - 如果您有自己的每个枚举常量的实现,则可以使用此方法。(或者您可以省略使用抽象方法,并在 Java 中使用每个枚举常量的自定义值 Enum 和自定义值)

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

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();
}
Run Code Online (Sandbox Code Playgroud)

如果此方法对于所有枚举常量都是通用的,那么请考虑使用接口。(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());
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

public class TestEnums{

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

        ColorInterface color = Color.RED;
        color.inLowerCase();
     }
}
Run Code Online (Sandbox Code Playgroud)

出去:

STOP
red
Run Code Online (Sandbox Code Playgroud)

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


KaN*_*011 6

就像 @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);
  }
}
Run Code Online (Sandbox Code Playgroud)

然后可以像这样使用枚举:

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

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