65.9K
CodeProject 正在变化。 阅读更多。
Home

秘密类或我如何停止计数并爱上枚举器

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.92/5 (35投票s)

2011 年 5 月 17 日

CPOL

3分钟阅读

viewsIcon

52865

了解如何在 Java 中使用枚举。

引言

本文将探讨 `enum` 类型的一些用途。 我不知道你怎么样,但我喜欢使用枚举。人们普遍认为 `enum` 类型提供了一组可能的值,并且是 `switch` 语句所必需的。就这些了吗?大错特错。

`enum` 类型是一个类。记住这一点,`enum` 的可扩展性就非常强大。它不仅仅可以用来表示属性的固定值,还可以用于更多用途。

一切皆对象

我从一个简单的前提开始。`enum` 类型定义了一个具有固定数量实例的类。 就像任何类一样,它可以有成员变量和方法,在一个简单的结构中提供整个 Java 世界。

public enum Season
{
   SUMMER,
   WINTER,
   AUTUMN,
   SPRING
}

这里有一个类,名为 `Season`,它有四个固定的实例。重要的是要记住这一点,因为你拥有的四个对象正是赋予 `enum` 简单结构和强大力量的原因。这种力量誓要用于善途。

`enum` 的常见用途是在 `switch` 语句中,例如:

String getForcast(Season season)
{
  switch (season)
  {
     case SUMMER:
     {
        return "Sun, sun, sun";
     }
     case AUTUMN:
     {
        return "Cold and blustery";
     }
     case WINTER:
     {
        return "Snow and ice";
     }
     case SPRING:
     {
        return "Overcast with showers";
     }
  }
  return null;
}

“等等!枚举器的元素都是对象,所以它们不能只是有一个方法来返回预测吗?” 你可能会问。说得好。这正是正确的做法。一个成员变量、一个方法和一个简单的构造函数,你就可以开始了。

public enum Season {
   SUMMER("Summer", "Sun, sun, sun"),
   WINTER("Winter", "Snow and ice"),
   AUTUMN("Autumn", "Cold and blustery"),
   SPRING("Spring", "Overcast with showers");

   private final String seasonName;
   private final String forcast;
   private Season(String seasonName, String forcast)
   {
      this.seasonName = seasonName;
      this.forcast = forcast;
      System.out.println("Creating " + this);
   }
   String getForcast()
   {
      return this.forcast;
   }

   public String toString()
   {
      return seasonName + "{" + forcast + '}';
   }
}

我包含了一个友好的字符串描述,并重写了 `toString()` 方法。

现在,不必在 `Season` 之外编写一个将值作为参数的方法,可以直接调用这些值来获取该值。

String forcast = Season.WINTER.getForcast();

存在的不可变性 [一个枚举]

如果你观察力敏锐,会发现成员变量都被标记为 `final`。这并非强制要求,但绝对值得鼓励。

因此,每个枚举都是一个对象,它可以拥有变量、方法,以及所有低空杂技表演。这些不仅仅是对象,它们的特殊状态意味着它们必须被视为不可变对象。它们并非完全不可变,但采取这种视角是好的。

由于是 `enum`,因此不需要 `hashCode()` 和 `equals()` 方法。每个实例都是唯一的,并且其相等性是固定的。因此,建议不要更改它们的状态。

需要功能吗?

我上面展示了枚举对象可以拥有属性和方法的方式。有时,某个操作的行为必须根据枚举的值而有所不同。这可以通过一个由每个枚举覆盖的抽象方法来实现,也可以通过一个功能类来提供行为。

首先是抽象方法

public enum Season
{

   SUMMER("Summer", "Sun, sun, sun")
   {
      boolean willItRain()
      {
         return false;
      }
   },
   //...
   SPRING("Spring", "Overcast with showers")
   {
      boolean willItRain()
      {
         return true;
      }
   };

   //...

   abstract boolean willItRain();
}

这可行,但可扩展性不高,如果只有几个覆盖,枚举类很快就会变得混乱。是时候将工作委托给一个功能类了;进入枚举工厂方法。

我们首先将所有预测移出 `enum` 类。我们有一个基类 `SeasonFunctions`,它是抽象的,然后是四个可爱的子类,它们可以以任何适合它们的方式实现功能。

abstract class SeasonFunctions {
   private final String seasonName;
   private final String forcast;

   SeasonFunctions(String seasonName,
         String forcast)
   {
      this.seasonName = seasonName;
      this.forcast = forcast;
      System.out.println("Creating " + this);
   }
   abstract boolean willItRain();
   abstract int dayTimeHigh();
   abstract int nightTimeLow();

      String getForcast()
   {
      return this.forcast;
   }

   public String toString()
   {
      return "SeasonFunctions{" + this.getSeasonName()  + "}";
   }

   String getSeasonString()
   {
      return this.getSeasonName() + "{" + this.getForcast() + '}';
   }

   private String getSeasonName()
   {
      return this.seasonName;
   }
}

历史

初步提交 - 更多内容即将到来。

© . All rights reserved.