在枚举内部提供函数是否被认为是“干净的”?

2024-01-06

我在源代码中发现了一些代码,这些代码基本上使用 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;
    }
}

人们可以发现这种方法得到推广对所有种类 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 解决方案。实际上是一件相当复杂的事情。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在枚举内部提供函数是否被认为是“干净的”? 的相关文章

  • 任务“:app:dexDebug”执行失败

    我目前正在处理我的项目 我决定将我的 Android Studio 更新到新版本 但在我导入项目后 它显示如下错误 Information Gradle tasks app assembleDebug app preBuild UP TO
  • Android - 如何访问 onResume 中 onCreate 中实例化的 View 对象?

    In my onCreate 方法 我正在实例化一个ImageButton View public void onCreate Bundle savedInstanceState super onCreate savedInstanceSt
  • java.lang.Class: 在 java 程序中初始化 log4j 属性文件时出错

    我正在尝试使用 log4j 运行独立的 java 程序 但在调试时收到以下消息 控制台上没有 log4j 相关日志 log Logger 1343 java lang Class ERROR in 18b4aac2 有人可以建议这里出了什么
  • Java 重写 hashCode() 得到 StackOverflowError

    所以我不太熟悉重写 hashCode 并且我似乎在 hashCode 方法中以某种方式进行了一些无限递归 这是我的场景 我有一个 DuplicateCache 类 它是一个缓存对象 用于检查系统中的重复对象 我有一个静态内部类 Duplic
  • Android - 除了普通 SSL 证书之外还验证自签名证书

    我有一个通过 SSL 调用 Web 服务的 Android 应用程序 在生产中 我们将拥有由受信任的 CA 签名的普通 SSL 证书 但是 我们需要能够支持自签名证书 由我们自己的 CA 签名 我已经成功实施了接受自签名证书的建议解决方案
  • PropertySources 中各种源的优先级

    Spring引入了新的注释 PropertySources对于所有标记为的类 Configuration since 4 0 需要不同的 PropertySource作为论证 PropertySources PropertySource c
  • Java 变量的作用域

    我不明白为什么这段代码的输出是10 package uno public class A int x 10 A int x 12 new B public static void main String args int x 11 new
  • 所有junit测试后的清理

    在我的项目中 我必须在所有测试之前进行一些存储库设置 这是使用一些棘手的静态规则来完成的 然而 在所有测试之后我不知道如何进行清理 我不想保留一些神奇的静态数字来引用所有测试方法的数量 我应该一直维护它 最受赞赏的方法是添加一些侦听器 该侦
  • 如何在java中使jpeg无损?

    有没有人可以告诉我如何使用编写 jpeg 文件losslessjava中的压缩 我使用下面的代码读取字节来编辑字节 WritableRaster raster image getRaster DataBufferByte buffer Da
  • 具有多种值类型的 Java 枚举

    基本上我所做的是为国家编写一个枚举 我希望不仅能够像国家一样访问它们 而且还能够访问它们的缩写以及它们是否是原始殖民地 public enum States MASSACHUSETTS Massachusetts MA true MICHI
  • 打印包含 JBIG2 图像的 PDF

    请推荐一些库 帮助我打印包含 JBIG2 编码图像的 PDF 文件 PDFRenderer PDFBox别帮我 这些库可以打印简单的 PDF 但不能打印包含 JBIG2 图像的 PDF PDFRenderer尝试修复它 根据 PDFRedn
  • 从 html 页面和 javascript 调用 java webservice

    我正在尝试从 javascript 调用 java 实现的 Web 服务 使用 NetBeans IDE 我读过很多关于 jQuery 和 AJAX 的内容 但我似乎无法掌握它 假设我的 Web 服务 WSDL 位于 http localh
  • OpenJDK 版本控制

    上下文 我想确保我们系统上安装的 Java 不受 CVE 2022 21449 的影响 java version 给出 openjdk version 11 0 7 2020 04 14 LTS OpenJDK Runtime Enviro
  • ExceptionHandler 不适用于 Throwable

    我们的应用程序是基于 Spring MVC 的 REST 应用程序 我正在尝试使用 ExceptionHandler 注释来处理所有错误和异常 I have ExceptionHandler Throwable class public R
  • 使用 Java 从 S3 上的文件在 S3 上创建 zip 文件

    我在 S3 上有很多文件 需要对其进行压缩 然后通过 S3 提供压缩文件 目前 我将它们从流压缩到本地文件 然后再次上传该文件 这会占用大量磁盘空间 因为每个文件大约有 3 10MB 而且我必须压缩多达 100 000 个文件 所以一个 z
  • 如何在android sdk上使用PowerMock

    我想为我的 android 项目编写一些单元测试和仪器测试 然而 我遇到了一个困扰我一段时间的问题 我需要模拟静态方法并伪造返回值来测试项目 经过一些论坛的调查 唯一的方法是使用PowerMock来模拟静态方法 这是我的 gradle 的一
  • 如何将实例变量传递到 Quartz 作业中?

    我想知道如何在 Quartz 中外部传递实例变量 下面是我想写的伪代码 如何将 externalInstance 传递到此作业中 public class SimpleJob implements Job Override public v
  • Java中有类似分支/跳转表的东西吗?

    Java有类似分支表或跳转表的东西吗 分支表或跳转表是 根据维基百科 http en wikipedia org wiki Branch table 用于描述使用分支指令表将程序控制 分支 转移到程序的另一部分 或可能已动态加载的不同程序
  • 使用 eclipse IDE 配置 angularjs

    我想开始使用 AngularJs 和 Java Spring 进行开发 我使用 Eclipse 作为 IDE 我想配置我的 Eclipse 以使这些框架无缝工作 我知道我可能要求太多 但相信我 我已经做了很多研究 你们是我最后的选择 任何帮
  • 尝试使用带有有效购买令牌的 Java Google Play Developer API v3 检索应用内购买信息时出现错误请求(无效值)

    当使用 Java Google Play Developer API 版本 3 并请求有效购买令牌的购买信息时 我收到以下异常 API 调用返回 400 Bad Request 响应以及以下消息 code 400 errors domain

随机推荐