Это действительно не связано с CRTP, а скорее с тем фактом, что для зависимого от базового доступа производного кода вам нужно квалифицировать вещи.
Изменение строки на
std::cout<protectedData<
разрешило ее.
См. , обращаясь к члену базового класса в производном классе .
Просто мои 2 цента: Вот код для Enum.java, как опубликовано Sun и частью JDK:
public abstract class Enum<E extends Enum<E>>
implements Comparable<E>, Serializable {
// [...]
/**
* Returns true if the specified object is equal to this
* enum constant.
*
* @param other the object to be compared for equality with this object.
* @return true if the specified object is equal to this
* enum constant.
*/
public final boolean equals(Object other) {
return this==other;
}
}
Да, это - как будто Вы создали одноэлементные экземпляры для каждого значения в перечислении:
public abstract class RoundingMode { public static final RoundingMode HALF_UP = new RoundingMode(); public static final RoundingMode HALF_EVEN = new RoundingMode(); private RoundingMode() { // private scope prevents any subtypes outside of this class } }
Однако , эти enum
конструкция приносит Вам различную пользу:
switch-case
управляющая структура. values
поле, которое 'сгенерировано' для каждого перечислимого типа сериализация является большим gotchya. Если бы я должен был использовать код выше вместо перечисления, вот то, как равенство идентификационных данных вело бы себя:
RoundingMode original = RoundingMode.HALF_UP; assert (RoundingMode.HALF_UP == original); // passes ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(original); oos.flush(); ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bais); RoundingMode deserialized = (RoundingMode) ois.readObject(); assert (RoundingMode.HALF_UP == deserialized); // fails assert (RoundingMode.HALF_EVEN == deserialized); // fails
Вы можете решать эту проблему без перечисления, с помощью техники, которая включает writeReplace
и readResolve
, (см. http://java.sun.com/j2se/1.4.2/docs/api/java/io/Serializable.html )...
я предполагаю, что точка - Java старается изо всех сил позволять Вам, используют идентификационные данные перечислимых значений для тестирования равенства; это - поощренная практика.
Да, == прекрасен - там, как гарантируют, будет просто единственной ссылкой для каждого значения.
Однако существует лучший способ записать Ваш круглый метод:
public int round(RoundingMode roundingMode) {
switch (roundingMode) {
case HALF_UP:
//do something
break;
case HALF_EVEN:
//do something
break;
// etc
}
}
даже лучше способ сделать это должно поместить функциональность в самом перечислении, таким образом, Вы могли просто звонить roundingMode.round(someValue)
. Это добирается до сути перечислений Java - они объектно-ориентированы перечисления, в отличие от "именованных значений", найденных в другом месте.
РЕДАКТИРОВАНИЕ: спецификация не очень ясна, но раздел 8.9 состояния:
ножка перечислимой литеры может содержать перечислимые константы. Перечислимая константа определяет экземпляр перечислимого типа. Перечислимый тип не имеет никаких экземпляров кроме определенных его перечислимыми константами.
Вот некоторый злой код, который Вы могли бы найти интересным. :D
public enum YesNo {YES, NO}
public static void main(String... args) throws Exception {
Field field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
Unsafe unsafe = (Unsafe) field.get(null);
YesNo yesNo = (YesNo) unsafe.allocateInstance(YesNo.class);
Field name = Enum.class.getDeclaredField("name");
name.setAccessible(true);
name.set(yesNo, "YES");
Field ordinal = Enum.class.getDeclaredField("ordinal");
ordinal.setAccessible(true);
ordinal.set(yesNo, 0);
System.out.println("yesNo " + yesNo);
System.out.println("YesNo.YES.name().equals(yesNo.name()) "+YesNo.YES.name().equals(yesNo.name()));
System.out.println("YesNo.YES.ordinal() == yesNo.ordinal() "+(YesNo.YES.ordinal() == yesNo.ordinal()));
System.out.println("YesNo.YES.equals(yesNo) "+YesNo.YES.equals(yesNo));
System.out.println("YesNo.YES == yesNo " + (YesNo.YES == yesNo));
}
== сравнивает ссылки двух объектов. Для перечислений гарантируется, что только будет один экземпляр, и поэтому для любых двух перечислений, которые являются тем же, == будет верно.
Ссылка:
http://www.ajaxonomy.com/2007/java/making-the-most-of-java-50-enum-tricks
(ничего не мог найти в документах солнца)
Перечисления являются великолепным местом для затора полиморфного кода.
enum Rounding {
ROUND_UP {
public int round(double n) { ...; }
},
ROUND_DOWN {
public int round(double n) { ...; }
};
public abstract int round(double n);
}
int foo(Rounding roundMethod) {
return roundMethod.round(someCalculation());
}
int bar() {
return foo(Rounding.ROUND_UP);
}
Обратите внимание, что при передаче перечисления через RMI / IIOP возникает проблема. См. Эту ветку:
http://www.velocityreviews.com/forums/t390342-enum-equality.html