我应该如何设计一个带继承的枚举?

时间:2017-01-20 17:47:08

标签: java inheritance enums functional-programming

我试图枚举解析数据的函数(ID3标签)。目前,我有一个看起来像这样的枚举:

enum Id3V1Layout {
  HEADER(range(fromString(), 0, 3)),
  TITLE(range(fromString(), 3, 33)),
  ARTIST(range(fromString(), 33, 63)),
  ALBUM(range(fromString(), 63, 93)),
  YEAR(range(fromString(), 93, 97)),
  /** length is 30 if zero bit != 0, else 28 */
  COMMENT(b -> range(fromString(), 97, b[125] == 0 ? 125 : 127).parse(b)),
  TRACK(b -> b[125] == 0 ? range(v -> (int) v[0], 126, 127).parse(b) : -1),
  GENRE(b -> b[127] < 0 ? null : Genre.values()[b[127]]);

  public final Id3FieldParser parser;

  static Id3FieldParser range(Id3FieldParser fn, int from, int to) {
    return b -> fn.parse(Arrays.copyOfRange(b, from, to));
  }

  static Id3FieldParser fromString() {
    return bytes -> new String(bytes).trim();
  }

  Id3V1Layout(Id3FieldParser parser) {
    this.parser = parser;
  }
}

(简短说明:每个元素定义如何解析特定字段。range是一个返回Id3FieldParser功能接口对象的方法。)

现在我的问题是:由于我想稍后实现ID3v2布局,如何使Id3V1Layout具有与Id3V2Layout相同的构造函数和方法?

我希望能够使用Id3Layout而不是硬编码Id3V1LayoutId3V2Layout

但枚举不能从抽象类继承,我不能在接口中定义构造函数。

那么如何使用一个具有两个枚举属性的公共类来定义具有不同参数的不同元素?

1 个答案:

答案 0 :(得分:1)

寻找这样的东西?

class Id3Layout {
    public interface ParseLayout {
        Id3FieldParser getParser();
    }
    private static Id3FieldParser range(Id3FieldParser fn, int from, int to) {
        return b -> fn.parse(Arrays.copyOfRange(b, from, to));
    }
    private static Id3FieldParser fromString() {
        return bytes -> new String(bytes).trim();
    }
    public enum Id3LayoutVersions {
        V1(Id3V1Layout.values()),
        V2(Id3V2Layout.values());

        private ParseLayout[] parseLayout;
        private Id3LayoutVersions(ParseLayout[] pl) {
            parseLayout = pl;
        }
        public ParseLayout[] getParseLayoutTokens() { return parseLayout; }
    }
    public enum Id3V1Layout implements ParseLayout {
        HEADER(range(fromString(), 0, 3)),
        ...;
        private Id3FieldParser parser;
        private Id3V1Layout(Id3FieldParser parser) {
            this.parser = parser;
        }
        public Id3FieldParser  getParser() { return parser; }
    }
    public enum Id3V2Layout implements ParseLayout {
        HEADER(range(fromString(), 0, 3)),
        ...;
        private Id3FieldParser parser;
        private Id3V2Layout(Id3FieldParser parser) {
            this.parser = parser;
        }
        public Id3FieldParser  getParser() { return parser; }
    }