人们可以发现这种方法得到推广对所有种类 https://stackoverflow.com/questions/18883646/java-enum-methods 的地方 https://dzone.com/articles/java-enums-how-to-make-much-more-useful,一个可能合理的例子是状态机 http://docsdrive.com/pdfs/academicjournals/jse/2010/215-230.pdf。枚举成员也在很晚的时候被采用斯卡拉语言 http://dotty.epfl.ch/docs/reference/enums/enums.html。因此,这显然不是 Java 的怪异特性,而是一项被证明是有用的理想特性。我个人在生产代码中一次又一次地使用它,特别是当需要一些静态映射时,从枚举到值或从枚举到函数。它允许结构紧凑、简洁的代码。
此外,IMO 已经令人信服地表明,如果我可以从中清除一些内容,那么最初问题中提出的 lambda 的使用方式比使用重写方法更可取。@johannes-kuhn 提供的链接 https://stackoverflow.com/questions/23361418/lambdas-in-the-classical-operation-enum-example.
因此我确实认为这被认为是良好的做法("clean" https://www.amazon.de/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882从 M.Fowler 和 R.Martin 的意义上来说)而不是坏的。如果没有明确地考虑这一点,那么也应该如此。
也就是说,有持续不断的评论认为枚举本身不干净 https://stackoverflow.com/questions/2268473/how-to-avoid-using-enums,因为它们引诱你使用不干净的 switch 语句(准确地说:代码味道,可能与干净相反),参考 M.Fowlers 第一版的“重构:改进现有代码的设计 https://rads.stackoverflow.com/amzn/click/com/0201485672”。而且,你知道,是他创造了“干净”(和“代码气味”)这个词。但是在他撤回了这一判决。
至于开关:必须考虑当您扩展枚举并且忘记扩展所有开关时会发生什么。我和我的同事发现引入单元测试很有用,它循环遍历枚举的所有项目并测试需要确保的内容。这个问题为 lambda 增强的枚举带来了另一个论点:在某些情况下你可以省去开关(switch someValue ... case Enum.x: dosmthg()
)有利于调用映射函数(someValue.dosmthg()
).
至于将这个问题纳入表达问题 https://stackoverflow.com/questions/3596366/what-is-the-expression-problem:
经过仔细检查,表达式问题看起来与该问题根本无关。从链接:"The Expression Problem is a new name for an old problem. The goal is to define a datatype by cases, where one can add new cases to the datatype and new functions over the datatype, without recompiling existing code, and while retaining static type safety (e.g., no casts)."
所以方法 A 和方法 B 都不可能出现表达式问题就像建议的那样,同样的方式一个人不能拥有哈维格-纳尔逊问题 https://en.wikipedia.org/wiki/Hadwiger%E2%80%93Nelson_problem跟他们。表达式问题本身就是一个问题,也是函数式和面向对象语言的一个难题,每种语言都有不同的解决方案,独立于此处给出的上下文。这是所示的 java 解决方案 https://koerbitz.me/posts/Solving-the-Expression-Problem-in-Haskell-and-Java.html声称既完整又有效,以及 Haskell 解决方案。实际上是一件相当复杂的事情。