java - 在被认为是 "clean"的枚举内部提供函数吗?

标签 java function enums

我在源代码中发现了一些代码,这些代码基本上使用 switch case 遍历枚举的每个可能值并调用适当的函数,该函数根据数据类型返回 Number 对象。

这是一个片段:

case TYPE_16BIT_SIGNED_BE:
    measurement = response.getRegisters().getShort(0);
    break;
case TYPE_16BIT_UNSIGNED_BE:
    measurement = response.getRegisters().getUnsignedShort(0);
    break;
case TYPE_16BIT_SIGNED_LE:
    measurement = response.getRegisters().getShortLE(0);
    break;

现在我的问题是,将此添加到枚举本身被认为是好的还是坏的做法?

这是我的意思的一个例子:

public enum SomethingType {
    INT((b) -> {
        return b.getInt(0);
    }),
    DOUBLE((b) -> {
        return b.getDouble(0);
    }),
    LONG((b) -> {
        return b.getLong(0);
    });

    private Function<ByteBuf, Number> getNumber;

    SomethingType(Function<ByteBuf, Number> getNumber) {
        this.getNumber = getNumber;
    }
}

最佳答案

可以发现这种方法得到推广 on all kind of places ,一个可能合理的例子是 state machines .枚举成员在 Scala language 中也很晚才被采用.因此,这显然不是 Java 的怪异功能,而是一个被证明有用的理想功能。我个人在生产代码中多次使用它,尤其是当需要一些静态映射时,从枚举到值或从枚举到函数。它允许结构紧凑、简洁的代码。

此外,IMO 已经令人信服地表明,如果我可以从 the link provided by @johannes-kuhn 中找到一些东西,那么在最初的问题中使用 lambdas 的方式比使用重写的方法更可取。 .

因此,我认为它被认为是好的做法("clean" 在 M.Fowler 和 R.Martin 的意义上)而不是坏的做法。如果没有明确考虑,它应该是。

也就是说,那里有持续的评论 consider enums as such not to be clean ,因为它们引诱您使用不干净的开关语句(准确地说:代码味道,可能与干净相反),引用 M.Fowlers 第一版“Refactoring: Improving the Design of Existing Code”。而且,您知道,正是他创造了“干净”(和“代码气味”)一词。但是在2005 edition他撤回了这一判断。

至于开关:必须考虑当您扩展枚举而忘记扩展所有开关时会发生什么。我和我的同事发现引入单元测试很有用,它循环遍历枚举的所有项目并测试需要确保的内容。该问题为 lambda 增强的枚举提供了另一个论据:在某些情况下,您可以保留开关(switch someValue ... case Enum.x: dosmthg())以支持调用映射函数(someValue.dosmthg()).

至于将此问题归入 Expression Problem 的建议:

经过仔细检查,表达式问题看起来与问题完全无关。来自链接:“表达式问题是旧问题的新名称。目标是通过案例定义数据类型,其中可以向数据类型添加新案例并在数据类型上添加新函数,而无需重新编译现有代码,同时保留静态类型安全(例如,无强制转换)。”

因此一个人不能像建议的那样用方法A和方法B来解决表达式问题,同样的方式一个人不能有Hadwiger–Nelson problem。跟他们。表达式问题本身就是一个问题,也是函数式语言和面向对象语言的难题,每种语言都有不同的解决方案,独立于此处给出的上下文。这是 a java solution shown声称既完整又有效,还有一个 Haskell 解决方案。实际上是一件相当复杂的事情。

关于java - 在被认为是 "clean"的枚举内部提供函数吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58232195/

相关文章:

具有两个指针的 C 函数

c# - 检查枚举是否有等于字符串的字段

java - Camel bean方法在另一个线程上运行

java - 如何将java字符串转换为日期对象

c++ - 用于分配成员函数指针的 lambda 表达式

r - 计算函数的反函数

typescript - 迭代 Typescript 中的枚举项

c# - 为什么默认枚举值是 0 而不是最小值?

java - 您如何使用 Data Snapshot 跨多个子节点检索数据?

java - 将整数显示为 Xs 的输出