Java使用抽象方法高级Enum并用于分支

时间:2014-01-27 20:18:59

标签: java oop enums

我是java的新手,在我的组织中遇到了一些高级的Enum代码。 我熟悉定义如下的枚举:public enum someList { VALUE1, VALUE2, ..}

但是在我遇到的高级枚举中,似乎还有很多......

/**
 * Defines ways to compare records in {@link ApplicationStatus} to see if they
 * are the same.
 */
public enum SourceStatusComparisonType
{
    CONTEXT_KEY
    {
        @Override
        public boolean compareKeys(SourceStatus source, ApplicationStatus status)
        {
            return source.getContextKey() == status.getSourceContextId();
        }
    },
    DATE
    {
        @Override
        public boolean compareKeys(SourceStatus source, ApplicationStatus status)
        {
            return source.getCobDate().equals(status.getCobDate());
        }
    };

    public abstract boolean compareKeys(SourceStatus source,
            ApplicationStatus status);
}

有人可以通过覆盖和重载的抽象方法来了解正在发生的事情。我不明白上面发生了什么。我被告知这被用来从使用它的代码中抽象出if / else块。但我不确定我理解。

提前谢谢。

3 个答案:

答案 0 :(得分:4)

每个枚举常量可以选择后跟一个类主体,如JLS §8.9中所指定。

  

枚举常量的可选类体隐式定义了一个匿名类声明(第15.9.5节),该声明扩展了直接封闭的枚举类型。班级团体由匿名班级的通常规则管理;特别是它不能包含任何构造函数。

因此,它就像使用抽象方法SourceStatusComparisonType创建一个抽象类compareKeys()。您创建该类的2个实例:

CONTEXT_KEY = new SourceStatusComparisonType() {
        @Override
        public void compareKeys() { .. }
    };

DATE = new SourceStatusComparisonType() {
        @Override
        public void compareKeys() { .. }
    };

并覆盖每个实例的抽象方法。没有该方法的实现,您不能拥有任何实例。

类似地,所有枚举常量必须在其各自的匿名类主体中提供抽象方法的实现。否则,你不能把那个方法当作抽象的。您必须提供一个主体,默认情况下将用于枚举常量,但不提供该方法实现:

public enum SourceStatusComparisonType
{
    CONTEXT_KEY
    {
        @Override
        public boolean compareKeys(SourceStatus source, ApplicationStatus status)
        {
            return source.getContextKey() == status.getSourceContextId();
        }
    },
    DATE
    {
        @Override
        public boolean compareKeys(SourceStatus source, ApplicationStatus status)
        {
            return source.getCobDate().equals(status.getCobDate());
        }
    },
    DEFAULT;

    public boolean compareKeys(SourceStatus source,
            ApplicationStatus status) {
//        return somedefaultvalue;
    }
}

因此,对于前两个常量,当您调用compareKeys方法时,将使用它们的具体实现,对于DEFAULT,将使用外部定义的方法。

答案 1 :(得分:1)

枚举类型可以像抽象方法一样具体,所有枚举常量都应该实现那些抽象方法。

在这里查看JSL http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.9.2并转到Example 8.9.2-4. Enum Constants with Class Bodies部分。

您甚至可以使用接口实现ENUM,而不是使用抽象方法。类似于public enum SourceStatusComparisonType implements StatusComparable

答案 2 :(得分:1)

你需要了解的关于Java中Enum的首要问题是它们是类,将它们视为类。因此,您学到的所有面向对象的设计/编程概念都适用于它们。

想象一下你制作的宇宙,其中只有3种生物,猫,牛和狗。一个实现是

public abstract class Animal
{
    private final String name;
    public Animal(String name) {
      this.name  = name;
    }

    public abstract String sayHello(Animal other);
}

public class Cat extends Animal
{
    public Cat(String name) {
       super(name);
    }

    @Override
    public String sayHello(Animal other) {
      System.out.println(this.name + " says Meow!!! to " + other.name);
    }
}

public class Cow extends Animal
{
    public Cow(String name) {
       super(name);
    }

    @Override
    public String sayHello(Animal other) {
        System.out.println(this.name + " says Moo!!! to " + other.name);
    }
}

public class Dog extends Animal
{
    public Dog(String name) {
       super(name);
    }

    @Override
    public String sayHello(Animal other) {
        System.out.println(this.name + " says Woof!!! to " + other.name);
    }
}

public Universe {
  public List<Animal> animals;

  public Universe(List<Animal> animals) {
    this.animals = animals;
  }

  public void run() {
    for (Animal animal : animals) {
      for (Animal other : animals) {
        if (other != animal) {
           animal.sayHello(other);
        }
      }
    }
  }
}

您对Universe感到满意并将其部署到生产环境中。只有发现,另一个恶意开发者已经为你的宇宙引入了一个新生物,一个僵尸

public class Zombie extends Animal
{
    public Zombie(String name) {
       super(name);
    }

    public String sayHello(Animal other) {
        System.out.println(this.name + " says Arrggggg!!! to " + other.name);
        eat(other);
    }

    private void eat(Animal other) {
        System.out.println("nomm nomm " + other.name);
    }
}

以打招呼为幌子的僵尸吃掉了他们遇到的所有动物。很快就会有没有猫,狗和奶牛离开。您决定部署Universe的第2版以防止这种情况并防范僵尸

public Universe2 {
  public List<Animal> animals;

  public Universe(List<Animal> animals) {
    this.animals = animals;
  }

  public void run() {
    for (Animal animal : animals) {
      for (Animal other : animals) {
        if (other != animal) {
           if (!(animal instanceof Zombie))
             animal.sayHello(other);
        }
      }
    }
  }
}

你现在很高兴,但你注意到猫的数量在减少,猫和狗不再是朋友,僵尸已经感染了他们的大脑,你部署了宇宙的第3版。

public Universe3 {
  public List<Animal> animals;

  public Universe(List<Animal> animals) {
    this.animals = animals;
  }

  public void run() {
    for (Animal animal : animals) {
      for (Animal other : animals) {
        if (other != animal) {
           if (!(animal instanceof Zombie) && !((animal instanceof Cat) && (animal instanceof Dog)))
             animal.sayHello(other);
        }
      }
    }
  }
}

在这个版本中,没有僵尸。猫和狗向奶牛问好,但彼此不和。宇宙处于平衡状态,但你有一种唠叨的感觉,即世界并非一切都是正确的。你沉睡在它上面,并意识到你可以接受类似于僵尸的攻击,你决定锁定宇宙并实施重写,从头开始并完全消除僵尸流行病。除了你喜欢打招呼的友善僵尸。

public Enum Animal {

    Cat {
        @Override
        public String sayHello(Animal other) {
          System.out.println(this.name + " says Meow!!! to " + other.name);
        }
    },
    Cow {
        @Override
        public String sayHello(Animal other) {
          System.out.println(this.name + " says Moo!!! to " + other.name);
        }
    },
    Dog {
        @Override
        public String sayHello(Animal other) {
          System.out.println(this.name + " says Woof!!! to " + other.name);
        }
    },
    Zombie {
        @Override
        public String sayHello(Animal other) {
          System.out.println(this.name + " says Argggg!!! to " + other.name);
        }
    };

    private String name;

    public Animal(String name) {
       this.name.
    }

    public String sayHello(Animal other);
}


public PerfectUniverse {
  public List<Animal> animals;

  public Universe(List<Animal> animals) {
    this.animals = animals;
  }

  public void run() {
    for (Animal animal : animals) {
      for (Animal other : animals) {
        if (other != animal) {
             animal.sayHello(other);
        }
      }
    }
  }
}

您已使用继承消除了条件if,但使用枚举锁定了可扩展性。您可以使用类来执行相同的操作,限制对包外的Animal的访问,并使派生类型成为final。这个enum Cat作为Cat扩展Animal的一个例子。具有重写方法的派生类型避免了使用if条件进行检查的实例。