2014-09-11 4 views
3

Метод getDeclaringClass() из Enum класс сначала смотрит вверх, является ли значение перечисления значением перечисления, то есть оно супер Enum. Если нет, то возвращение супер-класса независимо от класса данный экземпляр был рожден:Перечисление, которое не является частью Enum?

public final Class<E> getDeclaringClass() { 
    Class<?> clazz = getClass(); 
    Class<?> zuper = clazz.getSuperclass(); 
    return (zuper == Enum.class) ? (Class<E>)clazz : (Class<E>)zuper; 
} 

Как экземпляр, метод getDeclaringClass() работает на НЕ может быть instanceofEnum класс? Тип перечисления не может быть расширен, поэтому единственным суперклассом класса перечисления является Enum.

Так что - в следующем примере:

public enum Dirs { 
    NORTH, SOUTH, EAST, WEST 
} 

Dirs является подклассом Enum. Однако у Dirs не может быть самого подкласса - он не может быть расширен.
getDeclaringClass() любого из четырех направлений - например NORTH.getDeclaringClass() - Dirs, что составляет NORTH.getClass().

Исходный код getDeclaringClass() предполагает, что могут быть случаи, когда NORTH может иметь суперкласс, отличный от Enum. Я не понимаю, как это может произойти.

Что мне не хватает?

EDIT:

Более конкретно: Как может быть так, что NORTH.getDeclaringClass() будет НЕ возвращение NORTH.getClass(), который Dirs.

ответ

4

Не совсем верно, что вы не можете расширить свой собственный класс enum. Например, в случае

enum Dirs { 

    NORTH { 
     @Override 
     public Dirs getOppositeDirection() { 
      return SOUTH; 
     } 
    }, 
    SOUTH { 
     @Override 
     public Dirs getOppositeDirection() { 
      return NORTH; 
     } 
    }; 

    public abstract Dirs getOppositeDirection(); 
} 

Dirs на самом деле abstract класс, и его перечисление значений NORTH и SOUTH являются реализациями этого класса, которые обеспечивают тело абстрактного метода getOppositeDirection, что означает, что они простираются Dirs.

Так что, если вы будете называть

System.out.println(Dirs.NORTH.getDeclaringClass()); 
System.out.println(Dirs.SOUTH.getDeclaringClass()); 
System.out.println(Dirs.NORTH.getClass()); 
System.out.println(Dirs.SOUTH.getClass()); 

Вы увидите, как на выходе что-то вроде

class yourPackage.Dirs 
class yourPackage.Dirs 
class yourPackage.Dirs$1 
class yourPackage.Dirs$2 

, что означает, что getClass будет возвращать фактический класс, который реализует это перечисление, в то время как getDeclaringClass вернется Enum себя.

BTW: Enum не должен быть абстрактным, чтобы предоставить конкретную реализацию некоторому методу, приняв расширение enum. Вы также можете сделать что-то вроде

enum MyEnum { 
    FOO { 
     @Override 
     public String toString() { 
      return "Foo"; 
     } 
    }, 
    BAR{ 
     public String toString() { 
      return "baR"; 
     } 
    }; 
} 

и BAR.getDeclaringClass() вернется MyEnum, в то время как результат BAR.getClass() будет MyEnum$2.

1

Учитывайте, что в вашем перечислении есть поведение, тогда каждый экземпляр может иметь свою собственную реализацию.

public enum Dirs { 
    NORTH { 
     public Point move(Point p) { return p.move(0, 1); } 
    }, 

    SOUTH { 
     public Point move(Point p) { return p.move(0, -1); } 
    }, 

    EAST { 
     public Point move(Point p) { return p.move(1, 0); } 
    }, 

    WEST { 
     public Point move(Point p) { return p.move(-1, 0); } 
    } 

    public abstract Point move(Point p); 
} 

class Point{ 
    private final int x, y; 
    public Point(int x, int y) { this.x = x; this.y = y; } 
    public Point move(int dx, int dy) { return new Point(x + dx, y + dy); } 
} 

Теперь

assert Dirs.NORTH.getClass() != Dirs.SOUTH.getClass(); 

в то время как

assert Dirs.NORTH.getDeclaringClass() == Dirs.SOUTH.getDeclaringClass(); 

Надеется, что это помогает.

+0

Я считаю, что вы получили downvoted, потому что ваш код не будет компилироваться со стандартным классом 'java.awt.Pont', в то время как он верен для реализации, который я предоставил в редактировании. Надеюсь, вы не против, что я немного изменил ваш пост. – Pshemo

+0

О, я предоставил код только для иллюстрации подкласса в перечислении, фактический метод 'move' вместе с классом« Point »абсолютно произволен. Вероятно, должен удалить мой ответ, так как принятый ответ схож. – Vlad

+0

Поскольку ваш ответ правильный, я не думаю, что вы должны его удалить, но это не мое решение. – Pshemo

Смежные вопросы