请参阅
Java 枚举定义
和
为什么在java中枚举被声明为Enum>
供一般性讨论。在这里,我想了解如果定义了 Enum 类,因为
public class Enum<E extends Enum>
我正在使用此代码来测试我的想法,那么到底会破坏什么(不再是类型安全的,或需要额外的强制转换等):
interface MyComparable<T> {
int myCompare(T o);
}
class MyEnum<E extends MyEnum> implements MyComparable<E> {
public int myCompare(E o) { return -1; }
}
class FirstEnum extends MyEnum<FirstEnum> {}
class SecondEnum extends MyEnum<SecondEnum> {}
有了它,我无法找到任何好处在这种情况下。
附言。 我不允许这样做的事实
class ThirdEnum extends MyEnum<SecondEnum> {}
当 MyEnum 用递归定义时 是
a)不相关,因为对于真正的枚举,您不能仅仅因为自己无法扩展枚举而这样做
b) 不正确 - 请在编译器中尝试一下,看看它实际上能够编译,没有任何错误
PPS。我越来越倾向于相信这里的正确答案是“如果删除递归部分,什么都不会改变”——但我就是不敢相信。
Please see
Java Enum definition
and
Why in java enum is declared as Enum<E extends Enum<E>>
for general discussion. Here I would like to learn what exactly would be broken (not typesafe anymore, or requiring additional casts etc) if Enum class was defined as
public class Enum<E extends Enum>
I'm using this code for testing my ideas:
interface MyComparable<T> {
int myCompare(T o);
}
class MyEnum<E extends MyEnum> implements MyComparable<E> {
public int myCompare(E o) { return -1; }
}
class FirstEnum extends MyEnum<FirstEnum> {}
class SecondEnum extends MyEnum<SecondEnum> {}
With it I wasn't able to find any benefits in this exact case.
PS. the fact that I'm not allowed to do
class ThirdEnum extends MyEnum<SecondEnum> {}
when MyEnum is defined with recursion is
a) not relevant, because with real enums you are not allowed to do that just because you can't extend enum yourself
b) not true - pls try it in a compiler and see that it in fact is able to compile w/o any errors
PPS. I'm more and more inclined to believe that the correct answer here would be "nothing would change if you remove the recursive part" - but I just can't believe that.
发布评论
评论(5)
好吧,首先它会抱怨使用原始类型,但你可以这样做:
以获得相同的效果。
另外,使用这种类型的泛型,您可以执行以下操作:
在我看来,这可能会导致很多麻烦。更确切地说,您不能将 FirstEnum 类型的枚举与相同类型的枚举进行比较,您必须将其与其他类型的枚举进行比较,如果您有一个 你想要排序的。如果我设置
List
ListE
而不是?
,则该示例将无法编译,因为 SecondEnum 不是E extends MyEnum
类型(这会导致循环继承)。如果FirstEnum extends MyEnum
它将起作用(这意味着 SecondEnum 是 FirstEnum 的子类 - 正常的层次继承)。Well, first of all it would complain about using the raw type, but you could do:
for the same effect.
Also, with this type of generic you could do something like:
which to me seems like it could lead to a lot of trouble. More exactly you can't compare an enum of type FirstEnum with an enum of the same type, you have to compare it with an enum of the other type, which is really troublesome if you have a
List<FirstEnum>
that you want sorted. The example will not compile if i setE
instead o?
since SecondEnum is not of the typeE extends MyEnum<E>
(this would lead to circular inheritance). It will work ifFirstEnum extends MyEnum<FirstEnum>
though (which would mean that SecondEnum is a child class of FirstEnum - normal hierarchical inheritance).我相信这样做的一个令人信服的理由是它使 MyEnum 类中的代码更加类型安全。
考虑一下递归部分使这样的事情成为可能:
简而言之,递归性允许您将类型安全的方法放入 Enum 类中,您可以在任何 E 元素上调用这些方法,并且这些调用将是类型安全的。
I believe that a compelling reason to do that is that it makes the code in the MyEnum class more typesafe.
Consider that the recursive part makes such a thing possible:
In short, that recursivity lets you put typesafe methods in the Enum class that you can call on any E element, and these calls will be typesafe.
考虑
Enum.compareTo(E other)
。那:
Enum
上声明。您建议如何在没有当前限制的情况下实现这一目标?
这只是我想出的第一个……我相信还有很多其他的。基本上,它是一种说法,“你不应该尝试将所有枚举视为彼此等效......枚举本身是一个封闭的集合,但所有枚举都共享某些属性。”
Consider
Enum<E>.compareTo(E other)
.That:
ordinal()
method declared onEnum
.How would you propose making that work without the current constraint?
That's just the first one I came up with... I'm sure there are plenty of others. Basically it's a way of saying, "You shouldn't try to treat all enums as equivalent to each other... an enum is a closed set in itself, but all enums share certain properties."
如果您没有泛型类型参数,那么您将无法为您创建的枚举的特定子类型扩展
Comparable
。您可以忽略这一点,并创建自己的 MyEnum 类型,其行为大致相同,但不受不同 MyEnum 不可比较的限制:
这与定义操作的枚举的行为方式大致相同,但不是泛型类型安全实现遵循 LSP - MyEnum 不同子类的对象彼此可比较或相等,如果它们具有相同的序数值。
在这种情况下,如果您不重写
equals
,您就会失去x.comparesTo(y)=0
暗示x.equals(y)< 的约定/代码>;如果您确实覆盖 equals,那么在某些情况下,
x.equals(y)
并不意味着x == y
(对于其他值对象),而对于 Java 枚举来说,两者都是平等测试产生相同的结果。If you didn't have the generic type parameter, then you wouldn't be able to extend
Comparable<T extends Comparable>
for the specific subtype of enum you have created.You could ignore this, and create your own MyEnum type which behaves much the same but without the restriction that different MyEnum are not comparable:
This behaves in much the same way as an enum would for the operations defined, but instead of being a generic type safe implementation obeys LSP - objects of different subclasses of MyEnum are comparable or equal to each other if they have the same ordinal value.
In this case, if you don't override
equals
, you lose the convention thatx.comparesTo(y)=0
impliesx.equals(y)
; if you do override equals then there are cases wherex.equals(y)
does not implyx == y
(as for other value objects), whereas for Java enums both tests of equality produce the same result.将是非法的。这是相关的。编译器可以对
enum
有特殊规则,但如果可能的话,为什么不拥有完美的类型声明呢?would be illegal. that is relavant. compiler can have special rules with
enum
, but why not have a perfect type declaration if possible?