【问题标题】:'Subset' of Enum values in JavaJava中枚举值的“子集”
【发布时间】:2015-12-05 10:20:17
【问题描述】:

我有一个 Java 类,它的形式如下:-

public class Angle
{
    ANGLE_TYPE angleType;

    ANGLE_TYPE defaultAngleType = ANGLE_TYPE.RAD;

    enum ANGLE_TYPE
    {
        DEG, RAD, DEGMIN, DEGMINSEC;
    }
}

可以看出,该类定义了一个“枚举”。我的问题是关于实例变量“defaultAngleType”。我希望它是这样的,以便这个变量只能被分配值 RAD 或 DEG,否则抛出错误。

知道如何实现吗?

【问题讨论】:

  • 你将如何设置 defaultAngleType?因为你可以在 setter 方法中有一个 if 语句
  • 顺便说一句,naming convention for enumANGLE_TYPE 将是 AngleType 因为它实际上是一个 Java 类。 DEGRAD 等应该全部大写,因为它们确实是常量,AngleType 类型的静态类成员。我不是迂腐;我在自己使用枚举时发现,遵循此命名约定使我自己的代码更易于理解。诸如 NetBeans 之类的 IDE 可以识别枚举并为枚举名称(“AngelType”)使用特殊格式,使其更易于阅读,并且更少需要标记您的枚举。

标签: java enums


【解决方案1】:

您可以使用EnumSet。例如:

Set<ANGLE_TYPE> allowed = EnumSet.of(RAD, DEG);

【讨论】:

    【解决方案2】:

    enum 可能不是为此使用的最佳结构。

    我会应用一些基于继承的方法。

    interface Angle { }
    class DegMin implements Angle { }
    class DegMinSec implements Angle { }
    
    interface SpecialAngle extends Angle { } 
    class Deg implements SpecialAngle { }
    class Rag implements SpecialAngle { }
    

    有了这个层次结构,所有类都是Angle(s),但其中只有两个是SpecialAngle(s)(DegRad)。 p>

    那么,在你的课堂上,你会有:

    public class Angle
    {
        Angle angleType;
    
        SpecialAngle defaultAngleType = new Rad();
    }
    

    现在defaultAngleType 只能保存RadDeg 的实例。

    【讨论】:

      【解决方案3】:

      defaultAngleType 设为私有。在 defaultAngleType 的设置器中,检查参数,然后执行以下操作:

      public void setDefaultAngleType(ANGLE_TYPE type){
          if(type.equals(DEG) || type.equals(RAD))
              defaultAngleType = type;
          else
              throw new Exception();
      }
      

      【讨论】:

        【解决方案4】:

        Angle的构造函数设为私有,只允许通过静态工厂方法创建:

        private Angle(ANGLE_TYPE type, float value) {
           //...
        }
        
        static Angle degrees(float value) {
          return new Angle(ANGLE_TYPE.DEG, value);
        }
        
        static Angle radians(float value) {
          return new Angle(ANGLE_TYPE.RAD, value);
        }
        

        这意味着尝试创建其他一个会成为编译时错误,而不是运行时错误。

        当然,您需要通过将 angleType 变量设为私有并提供 getter 来控制对它的访问,因为您无法阻止其他人将该字段更改为禁止值之一。

        【讨论】:

        • 感谢您的回复...由于某种原因,这里不允许使用“谢谢”一词
        【解决方案5】:

        这是一个重新设计的建议:

        您可以声明Angle 始终以弧度表示,但有 4 个不同的构造函数:

        1. 弧度
        2. 度,分
        3. 度、分、秒

        构造函数 2 到 4 会立即将度/分/秒转换为弧度。

        或者您可以创建一个扩展 AngleDegreeAngle 类,该类将添加度/分/秒设置器和获取器。

        【讨论】:

          【解决方案6】:

          如果你不想使用 EnumSet,你可以通过这个方法做一个原始子集,虽然它确实需要相当多的样板和更多的字段保护。

          public class Angle {
          
              private ANGLE_TYPE angleType;
          
              private ANGLE_TYPE defaultAngleType = DEFAULT_ANGLE_TYPE.RAD.angleType;
          
              enum ANGLE_TYPE {
                  DEG, RAD, DEGMIN, DEGMINSEC;
              }
          
              enum DEFAULT_ANGLE_TYPE {
          
                  DEG(ANGLE_TYPE.DEG),
                  RAD(ANGLE_TYPE.RAD);
          
                  private ANGLE_TYPE angleType;
          
                  DEFAULT_ANGLE_TYPE(ANGLE_TYPE angleType) {
                      this.angleType = angleType;
                  }
          
              }
          
              public Angle(ANGLE_TYPE angleType, DEFAULT_ANGLE_TYPE defaultAngleType) {
                  this.angleType = angleType;
                  this.defaultAngleType = defaultAngleType.angleType;
              }
          
          }
          

          【讨论】:

            猜你喜欢
            • 2010-12-10
            • 1970-01-01
            • 2011-10-27
            • 2011-04-09
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2010-10-05
            • 1970-01-01
            相关资源
            最近更新 更多