Java 8 是否提供了访问者模式的替代方案?

2024-03-11

This https://stackoverflow.com/questions/2078978/functional-programming-vs-object-oriented-programming/2079678#2079678Stack Overflow 上的流行答案是这样描述函数式编程和面向对象编程之间的区别的:

当你有一组固定的对象时,面向对象语言就很好用运营 on things,并且随着代码的发展,您主要添加新的 事物。这可以通过添加实现的新类来完成 现有的方法和现有的类保持不变。

当你有一组固定的语言时,函数式语言就很好用things, 和 随着代码的发展,您主要添加新的运营在现有的 事物。这可以通过添加计算的新函数来完成 与现有的数据类型,并且现有的函数保持不变。

假设我有一个Animal界面:

public interface Animal {
    public void speak();
}

我有一个Dog, Cat, Fish, and Bird全部实现该接口。如果我想添加一个新方法Animal named jump(),我必须遍历所有子类并实施jump().

访问者模式可以缓解这个问题,但似乎通过 Java 8 中引入的新功能特性,我们应该能够以不同的方式解决这个问题。在scala我可以轻松地使用模式匹配,但 Java 还没有真正做到这一点。

Java 8 真的让添加新内容变得更容易了吗?运营在现有的事物上?


您想要完成的任务虽然令人钦佩,但在大多数情况下并不适合 Java。但在我开始之前……

Java 8 向接口添加了默认方法!您可以根据接口中的其他方法定义默认方法。这已经可用于抽象类。

public interface Animal {
    public void speak();
    public default void jump() {
        speak();
        System.out.println("...but higher!");
    }
}

但最终,您将必须为每种类型提供功能。我没有看到添加新方法和创建访问者类或部分函数之间有很大区别。这只是一个位置问题。您想按操作或对象组织代码吗? (功能或面向对象、动词或名词等)

我想我想要表达的观点是,Java 代码是按“名词”组织的,其原因不会很快改变。

访问者模式和静态方法可能是通过操作组织事物的最佳选择。然而,我认为当访问者并不真正依赖于他们访问的对象的确切类型时,他们才是最有意义的。例如,动物访客可能用于让动物说话然后跳跃,因为所有动物都支持这两件事。跳跃访客对我来说没有多大意义,因为这种行为本质上是针对每种动物的。

Java 使真正的“动词”方法有点困难,因为它根据参数的编译时类型选择要运行的重载方法(见下文和根据参数的真实类型选择重载方法 https://stackoverflow.com/questions/1572322/overloaded-method-selection-based-on-the-parameters-real-type)。方法仅根据类型动态调度this。这就是继承是处理此类情况的首选方法的原因之一。

public class AnimalActions {
    public static void jump(Animal a) {
        a.speak();
        System.out.println("...but higher!");
    }
    public static void jump(Bird b) { ... }
    public static void jump(Cat c) { ... }
    // ...
}
// ...
Animal a = new Cat();
AnimalActions.jump(a); // this will call AnimalActions.jump(Animal)
                       // because the type of `a` is just Animal at
                       // compile time.

您可以通过使用来解决这个问题instanceof以及其他形式的反思。

public class AnimalActions {
    public static void jump(Animal a) {
        if (a instanceof Bird) {
            Bird b = (Bird)a;
            // ...
        } else if (a instanceof Cat) {
            Cat c = (Cat)a;
            // ...
        }
        // ...
    }
}

但现在您只需执行 JVM 旨在为您完成的工作。

Animal a = new Cat();
a.jump(); // jumps as a cat should

Java 有一些工具可以更轻松地向大量类添加方法。即抽象类和默认接口方法。 Java 专注于根据调用方法的对象来调度方法。如果你想编写灵活且高性能的 Java,我认为这是你必须采用的一种习惯用法。

P.S.因为我是That Guy™ 我将介绍 Lisp,特别是 Common Lisp 对象系统 (CLOS)。它提供了基于所有参数进行调度的多种方法。这本书实用 Common Lisp甚至提供与 Java 有何不同的示例 http://www.gigamonkeys.com/book/object-reorientation-generic-functions.html#multimethods.

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

Java 8 是否提供了访问者模式的替代方案? 的相关文章

  • JavaFX Platform.runLater 的使用以及从不同线程访问 UI

    我有几个问题Platform runLater 我有一个 JavaFX 应用程序类 在这个类中 我运行一个线程 该线程从网络套接字读取数据 现在当我创建一个新的Stage在线程内部 系统抛出异常 JavaFX 事件调度程序线程和我的网络读取
  • Java:高性能消息传递(单生产者/单消费者)

    我最初问这个问题here https stackoverflow com questions 3367192 java is while true loop in a thread bad whats the alternative 但我意
  • 无法实例化接收器 com.parse.GcmBroadcastReceiver

    我正在编写一个使用 GCM 通知和解析推送的离子应用程序 这个应用程序正在使用这些插件 com ionic keyboard 1 0 3 Keyboard com phonegap plugins PushPlugin 2 4 0 Push
  • 初级 Java 计数器代码

    我的教授希望我这样做 使用下面的 Counter 接口写入多个可互换计数器 public interface Counter Current value of this counter int value Increment this co
  • 哈希码是否用于加速集合中的对象查找?

    IIUC 相同类型的两个不同对象可以存储在 HashSet 中 即使两个对象在以下情况下返回相同的值 hashCode 叫做 例如根据本文 https eclipsesource com blogs 2012 09 04 the 3 thi
  • 用 java 编写解释器时的 switch 或 if 语句

    当前的作业需要我编写一个程序 以一种非常微小且基本的编程语言 行为有点像 FORTRAN 来读取包含指令的文件并执行这些指令 基本上它是我猜的语言的简单解释器 它是完全线性的 所有语句都是按顺序定义的 并且只有字符串和整数变量 我需要查找和
  • Java 唤醒休眠线程

    我阅读了其他帖子 但没有找到我正在寻找的确切答案 所以我希望有人能给出一些澄清 我有一个将运行一段时间的程序 我有一些在后台运行的线程来执行各种任务 为了简单起见 让我们考虑 3 个线程 ThreadA每 10 秒执行一次任务 其中Thre
  • 支持通过 OAuth 进行 Facebook/Twitter 身份验证的 CAS 服务器

    我正在寻找一个支持 Facebook Twitter 通过 OAuth 进行单点登录身份验证的 CAS 服务器 我检查过 JASIG CAS 服务器 但它看起来不支持它们 我的 java web 应用程序基于 Spring Security
  • 列表推导式和 for 循环中的 Lambda 表达式[重复]

    这个问题在这里已经有答案了 我想要一个 lambda 列表 作为一些繁重计算的缓存 并注意到这一点 gt gt gt j for j in lambda i for i in range 10 9 9 9 9 9 9 9 9 9 9 Alt
  • SimpleDateFormat 将 lenient 设置为 false 时出现异常

    为什么这段代码会抛出无法解析日期的异常 SimpleDateFormat f new SimpleDateFormat yyyy MM dd T HH mm ss 000Z f setLenient false String dateStr
  • 在 eclipse 之外将 Spring MVC 应用程序部署到 tomcat 的幕后会发生什么?

    我猜想使用像 eclipse 这样很棒的 IDE 的一个缺点是你会忽略应用程序幕后发生的事情 我是一名 Ruby 开发人员 所以不是一名 Java 老手 所以我一直在用 java 编写一个项目 并使用 spring 框架进行 IOC 和 M
  • 抽象类或接口。哪种方式是正确的?

    有两种方法可以选择抽象类或接口 微软解决方案和Oracle解决方案 微软 设计指南 请使用抽象 在 Visual Basic 中为 MustInherit 类而不是接口来将协定与实现分离 http msdn microsoft com en
  • 在服务器内部调用 Web 服务

    我有一个网络服务 getEmployee 当传递 id 时 它会获取单个员工的员工详细信息 同一服务器上的另一个 Web 服务 getEmployeeList 当传递一个部门时 它会获取整个员工列表 这将获取部门的 ID 然后调用 getE
  • 找不到符号assertEquals

    我正在尝试为计算器编写第一个单元测试 但 NetBeans 说它找不到该符号assertEquals和注释 Test 我应该包括一些东西吗 我正在使用 NetBeans 7 3 1 和 W7 package calculator impor
  • scala中的协变类型参数需要在java接口中保持不变

    我有一个看起来像这样的特征 一些进一步的信息可以在我自己提出了这个相关问题 https stackoverflow com questions 3695990 inheritance and automatic type conversio
  • Selenium - 等待网络流量

    我们将 Selenium 与 Java API 和一些 Javascript 用户扩展一起使用 我们在应用程序中使用了大量 AJAX 调用 我们的许多测试随机失败 因为有时 AJAX 调用完成得比其他时候慢 因此页面未完全加载 我们通过等待
  • 方法签名中带或不带synchronized关键字的方法具有相同的字节码

    对于以下 2 个类 获得相同的 Java 字节码 java版本 java 版本 1 8 0 181 Java TM SE 运行时环境 构建 1 8 0 181 b13 Java HotSpot TM 64 位服务器 VM 内部版本 25 1
  • 如何从spark中的hbase表中获取所有数据

    我在 hbase 中有一个大表 名称为 UserAction 它具有三个列族 歌曲 专辑 歌手 我需要从 歌曲 列族中获取所有数据作为 JavaRDD 对象 我尝试了这段代码 但效率不高 有更好的解决方案来做到这一点吗 static Spa
  • 我找不到 IntelliJ 快捷方式

    我使用 vim 一段时间 我知道有一个 intellij vim 插件 我很好奇内置的 IntelliJ 文本导航存在什么 如何打开实时模板来创建模板 如何查看以 tr 开头的现有模板列表 如何进行全局搜索并在当前文档中进行搜索 然后转到下
  • Libgdx 和 Google 应用内购买结果

    我遵循了这些指示 https github com libgdx libgdx wiki Interfacing with platform specific code使用 ActionResolver 接口集成 Libgdx 和原生 An

随机推荐

  • 如何在 Qt 子目录项目中设置构建顺序

    我有一个包含 5 6 个库和一个可执行文件的项目 可执行文件依赖于库 并且某些库依赖于其他库 如何指定构建顺序 以便在需要依赖项之前构建依赖项 Update 2021 年 2 月 2018 年 10 月 Qt 决定弃用 Qbs https
  • 与表无关的外键?

    首先 我确实读过这个 StackOverflow 问题 https stackoverflow com questions 294969 sql one foreign key references primary key in one o
  • PKCS12 到 JKS 转换失败

    我正在尝试使用以下命令将 PKCS12 格式文件转换为 JKS 密钥库 keytool v importkeystore trustcacerts srckeystore cert p12 srcstoretype PKCS12 destk
  • emacs isearch 整个缓冲区的延迟突出显示

    isearch 的默认行为是突出显示当前窗口中匹配的世界 我怎样才能改变这种行为 让它突出显示整个当前缓冲区中匹配的世界 也许您正在寻找高亮 命令 以便在执行其他操作时在整个缓冲区中突出显示内容 M shC h lists Global B
  • KeyListener 在 JPanel 中不起作用?

    我正在尝试在 java 类中使用 KeyListener 但由于某些奇怪的原因它不接受输入 我最近刚刚遇到这个问题 在它运行完美之前 但发生了一些变化 现在它不接受任何输入 这是我的代码的摘录 public class SquarePane
  • 嵌套文档 MongoDB 中的求和

    我试图对一系列文档中的一些值求和 但没有成功 这是文件 db Cuentas find pretty Agno 2013 Egresos Fecha 28 01 2013 Monto 150000 Detalle Pago Nokia Lu
  • 在 Microsoft Excel 中将值向上舍入到最低值

    我正在 Excel 中编写一个公式 其中我要潜水 2 个数字 并且我不需要十进制值 我尝试使用 ROUND 5 10 0 但它的舍入范围为 0 5 到 1 但我的要求是 0 0 99 应该评估为0 同样 2 2 990 应评估为 2 E g
  • android RadioButton按钮可绘制重力

    我正在动态生成 RadioButtons RadioButton radioButton new RadioButton context LayoutParams layoutParams new LayoutParams radioWid
  • 使用函数的返回类型指定类型提示

    我想将变量的类型暗示为特定函数的返回类型 无需手动指定函数的返回类型是什么 我无法以可用作另一个变量提示的方式从函数中提取返回值类型 def dostuff gt T StuffContainer namedtuple StuffConta
  • 为什么 SortedList.add() 会抛出 UnsupportedOperationException?

    非常简单的代码 import javafx collections FXCollections import javafx collections ObservableList import javafx collections trans
  • 在 Firebase 中的 SafetyNet 的应用程序检查中取消注册应用程序

    我已在 firebase 控制台中的应用程序检查中的 safetyNet 中注册了应用程序 但是现在我必须取消注册 将应用程序添加到 safetyNet 中或禁用 safetyNet 我该怎么做 这有点棘手且不直观 因为您无法删除产品设置中
  • 在 Laravel 中使用同步在数据透视表中分离

    我发生了一些奇怪的事情 我无法理解 想知道是否有人可以帮助我弄清楚发生了什么事 我有 2 个表 评估者 流程 和一个数据透视表 process assessor 我正在尝试使用评估者的流程更新数据透视表 因此我有一个表单 在提交时会传递给此
  • Devise for Rails 4:为什么要将用户配置文件数据保存在与 Devise 用户模型表不同的单独表中

    我正在使用 devise 根据文档建议 我有一个用户模型 用于 devise 和一个用于用户数据 例如姓名 工作等 的配置文件模型 为什么仅将所有这些属性存储在设计用户模型表 只是好奇 如果 gem 更改了表定义 则向外部源指定的表添加字段
  • URL 缩短工具如何保证 URL 不会过期? [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 stackoverflow 上以及互联网上的其他地方都有很多关于 URL 缩短器的问题 例如 如何编写 URL 缩短器代码 https stackov
  • 本地删除文件后SVN提交错误

    我有一个使用 Netbeans 6 1 构建的项目 并且使用 SVN 我删除了本地计算机上的一些文件 然后尝试将更改提交到 SVN 存储库 提交失败并显示错误消息 C path to project myfile 的条目没有 URL 其中
  • 自定义clickonce下载屏幕

    众所周知 当我们双击 clickonce 安装的应用程序时 会弹出一个 clickonce 屏幕 显示 正在验证系统要求 然后 如果服务器中有更新的版本 则单击更新本地安装的版本 并启动应用程序 有什么方法可以定制整个过程 这并不意味着我想
  • Backbone.js:未到达路由器回调

    我在获取简单的应用程序示例进行路由时遇到问题 我正在使用backbone on rails gem 这是我的 App js coffee window App Models Collections Views Routers documen
  • 使用 Autodesk API 下载文档

    我正在尝试从 BIM 360 Docs 下载文档 如果我想下载类型为 type items autodesk bim360 File 我只需要获取bucketID和objectID projects
  • 如何更改特定类名的所有类名元素

    如何更改特定类名的所有类名元素 我的意思是 假设我有 3 个带有 MyClass 类的 div 我想在 JavaScript 中将它们的类名更改为 notMyClass 该怎么做 div class MyClass div div clas
  • Java 8 是否提供了访问者模式的替代方案?

    This https stackoverflow com questions 2078978 functional programming vs object oriented programming 2079678 2079678Stac