枚举的子类化
有没有一种简单的方法来子类 Java enum
?
我问这个问题是因为我有大约 10 个实现相同接口的代码,但它们对某些方法也有相同的实现,因此我想通过将所有相同的实现放置在扩展 Enum 它也是我需要的所有其他类的超类。
或许事情并没有我想象的那么简单?
提前致谢
is there a simple way to subclass a Java enum
?
I ask this because I have like 10 of them that implement the same interface but they also have the same implementation for some methods so I would like to reuse the code by placing all the same implementations in middle object that extends Enum
and it is also the superclass of all the others I need.
Maybe it is not so straightforward as I think?
Thank in advance
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
你做不到,因为语言不允许你这样做。出于一个很好的逻辑原因:只有当您可以从子类中删除一些枚举值而不是添加新的枚举值时,子类化枚举才有意义。否则你就会违反里氏替换原则。
简而言之,只要需要超类的实例,子类的每个实例都应该是可接受的。如果您在枚举子类中添加新的枚举成员,那么只知道超级枚举的人显然无法接受。
有关更多详细信息和可能的替代方案,请参阅我之前的回答。
在你的具体情况下,@Jason的建议可能会提供一个很好的解决方案(对他来说+1:-)
更新@OrangeDog的评论
好点,我上面有点草率:-)在实施方面你是对的。然而,从逻辑的角度来看,枚举类型是由其有效值集完整描述的。一般来说,真正的子类是其超类的特化。换句话说,有效子类实例集(应该)始终是超类实例集的子集。 (每只狗都是动物,但并非每只动物都是狗。)
You can't do it, since the language does not allow you. And for a good logical reason: subclassing an enum would only make sense if you could remove some enum values from the subclass, not add new ones. Otherwise you would break the Liskov Substitution Principle.
This in brief states that every instance of a subclass should be acceptable whenever an instance of a superclass is expected. If you add a new enum member in an enum subclass, that clearly can't be accepted by someone knowing only the super enum.
For more details and possible alternatives, see this earlier answer of mine.
In your concrete case, @Jason's suggestion may offer a good solution (+1 for him :-)
Update to @OrangeDog's comment
Good point, I was a bit sloppy above :-) Implementation-wise you are right. However, from the logical point of view an enum type is fully described by the set of its valid values. And generally, a proper subclass is a specialization of its superclass. In other words, the set of valid subclass instances is (should be) always a subset of the superclass instance set. (Every dog is an animal, but not every animal is a dog.)
使用静态帮助器类怎么样?
How about using a static helper class?
使用 Java 8,您可以使用 默认方法。
如果需要访问 Enum 类实现的方法,请将签名添加到接口中:
With Java 8 you can put the shared implementation in the interface using default methods.
If access to methods implemented by the
Enum
class is required, add the signature to the interface:尝试使用 Apache commons 包中的 Enums,您可以在其中子类化 Enums。
不知道这是否会帮助你。
Try using Enums from Apache commons package, where you can subclass Enums.
Dont know if this will help you.
虽然 Java 中已有关于抽象枚举的提议,但人们认为其好处还远远不够。太低而无法抵消成本。您必须坚持转发方法调用。
Whilst there have been proposals for abstract enums in Java, the benefits are considered far too low to outweigh the costs. You'll have to stick with forwarding method calls.
该语言不允许您这样做,因为枚举是为有效表示枚举值而设计的,而不是为了实现代码。尝试使用另一种模式,例如静态帮助器(实用程序)类。
The language does not allow you to do so, as Enums are designed for representing enumerated values efficiently, not for implementing code. Try using another pattern like a static helper (utility) class.
@Jason S 提供了一个很好的答复,但是静态方法会让你失去 OOP 的潜力。
代表团呢?我的意思是:
定义一个通用接口“I_A”,在其中定义所有 getter/setter 和所有其他方法。
定义一个“类似结构”的类“S_C”:它只实现 getter 和 setter,其他方法都是空的,因为无用。
为了使您的枚举更短(就代码行而言),请定义第二个接口“I_A_Delegating”,它扩展了第一个接口,并具有一个“I_A”类型的附加 getter/setter(它是我们的委托者),并且感谢Java 的默认方法,将 getter/setter 定义为调用委托者的 getter/setter。
您的所有枚举都实现“I_A_Delegating”并具有“S_C”的本地实例
代码示例:
@Jason S has offered a good reply, but the static method make you lose the OOP's potentialities.
What about delegation? I mean:
Define a common interface "I_A" where you defines all getters/setters and all other methods.
Define a "struct-like" class "S_C" : it implements only the getters and setters, other methods are empty because are useless.
To make your enumerations shorter (in terms of lines of code), define a second interface "I_A_Delegating" that extends the first ones, has an additional getter/setter of type "I_A" (it's our delegator) and, thanks to Java's default methods, define the getter/setter as calling the delegator's getter/setter.
All of your enumerations implements "I_A_Delegating" and has a local instance of "S_C"
Code example: