- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
This关于函数式编程和面向对象编程之间的区别,Stack Overflow 上的流行答案是这样说的:
Object-oriented languages are good when you have a fixed set of operations on things, and as your code evolves, you primarily add new things. This can be accomplished by adding new classes which implement existing methods, and the existing classes are left alone.
Functional languages are good when you have a fixed set of things, and as your code evolves, you primarily add new operations on existing things. This can be accomplished by adding new functions which compute with existing data types, and the existing functions are left alone.
假设我有一个 Animal
界面:
public interface Animal {
public void speak();
}
我有一只Dog
、Cat
、Fish
和Bird
,它们都实现了该接口(interface)。如果我想向 Animal
添加一个名为 jump()
的新方法,我将不得不遍历所有子类并实现 jump()
.
访问者模式可以缓解这个问题,但似乎随着 Java 8 中引入的新功能特性,我们应该能够以不同的方式解决这个问题。在 scala
中,我可以轻松地使用模式匹配,但 Java 还没有。
Java 8 真的让在现有事物上添加新的操作变得更容易了吗?
最佳答案
您要完成的工作虽然令人钦佩,但在大多数情况下并不适合 Java。但在我开始之前......
Java 8 为接口(interface)添加了默认方法!您可以根据接口(interface)中的其他方法定义默认方法。这已经可用于抽象类。
public interface Animal {
public void speak();
public default void jump() {
speak();
System.out.println("...but higher!");
}
}
但最终,您将不得不为每种类型提供功能。我没有看到添加新方法和创建访问者类或部分函数之间的巨大差异。只是地点的问题。你想按 Action 或对象组织你的代码吗? (功能性或面向对象,动词或名词等)
我想我想表达的意思是 Java 代码是按“名词”组织的,原因不会很快改变。
访问者模式和静态方法可能是您按操作组织事物的最佳选择。但是,我认为访问者在不真正依赖于所访问对象的确切类型时最有意义。例如,可以使用 Animal visitor 让动物说话然后跳跃,因为所有动物都支持这两件事。跳跃访客对我来说意义不大,因为这种行为对于每只动物来说都是固有的。
Java 使真正的“动词”方法有点困难,因为它根据参数的编译时类型选择要运行的重载方法(参见下文和 Overloaded method selection based on the parameter's real type)。方法仅根据 this
的类型动态分派(dispatch)。这就是继承是处理此类情况的首选方法的原因之一。
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 有一些工具可以更轻松地向大量类添加方法。即抽象类和默认接口(interface)方法。 Java 专注于基于调用方法的对象来分派(dispatch)方法。如果您想编写灵活且高性能的 Java,我认为这是您必须采用的一种习惯用法。
P.S. 因为我是 That Guy™,所以我将介绍 Lisp,特别是 Common Lisp Object System (CLOS)。它提供了基于所有参数进行分派(dispatch)的多重方法。 Practical Common Lisp 一书甚至提供了 an example of how this differs from Java .
关于java - Java 8 是否提供了访问者模式的替代方案?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29090179/
我正在尝试为玩具语言实现一个解析器。 我已经编写了语法,但是当我尝试从 CST 创建 AST 时遇到了问题。 我定义了一个继承自 MyParserVisitor 的类哪里ASTNode是一个虚拟类,我
我想创建子类对象,它会与其他子类对象做出不同的 react (类可以欢迎另一个类,但不是全部)代码原理源自访客设计模式: class A { public : virtual bool isW
我正在玩 boost A* 算法,从在以下位置找到的示例开始:http://www.boost.org/doc/libs/1_37_0/libs/graph/example/astar-cities.
我正在为我的网站构建一个访问者和点击率计数器,当然,访问者每天是一个唯一的 ip,点击率是每次请求页面时! 我已经创建了数据库和系统来插入和更新我保存统计信息的表! 我正在苦苦挣扎的是,如何对日期进行
如何放弃使用 IE6 浏览我的网站? 就像是 : 如果 ie6 => 死 我正在使用 ASP.Net 谢谢 最佳答案 在asp.net中你可以查看Request.Browser在 Session_st
我目前正在编写解析器。解析器生成一个 AST,然后我使用各种遍历来处理它。 AST 是(简化的): type LiteralExpr = { readonly kind: 'literal',
我正在使用 Antlr4 的 C++ 访问者 api 来遍历解析树。但是,我正在努力使其正常运行。也就是说,我不确定如何使用 visitChildren(ParseTree *tree) 调用。 我为
我的问题是理论性的,而不是如何去做。我想知道专家们如何处理我将在下面描述的情况。 我有一个使用 Angular 和 Breeze 的 SPA。身份验证是基于 token 的。我在 Angular 中设
我有一棵树(在图形意义上)表示一棵树(在物理意义上)。树表示为 BGL 邻接列表,其中每个顶点包含半径和位置属性,即,我的图以以下形式定义 struct TreeVertexType { doub
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题吗? Update the question所以它是on-topic用于堆栈溢出。 关闭 10 年前。 Improve thi
是否可以将域限制为仅允许使用特定浏览器的访问者? 我正在构建一个应用程序,到目前为止它只在 Chrome 中进行过测试,所以我只想在 Beta 测试期间允许 Chrome 用户。基本上,我想在进行测试
你好,我正在尝试实现一个 AST Clang 访问者,这是我的代码。 class ExampleVisitor : public RecursiveASTVisitor { private:
我想构建一个访问者(用于 dikstra),并将 initialise_vertex 用作“颜色映射”修饰符。我想根据条件从搜索中排除一些顶点。所以我想在算法的初始部分将一些顶点设置为“黑色”。 cl
我正在尝试编写一个网站,提示每 10,000 名访问者输入一封可以存储在文本文件中的电子邮件。 我设置了一个点击计数器,它将访问者总数输出到一个文本文件中,因此是否可以将脚本设置为类似于 "如果 nu
我正在尝试将 AST 与 ANTLR4 一起使用,并使用以下文件: 生成器.java import org.antlr.v4.runtime.ANTLRInputStream; import org.
在 BGL 中,我不太明白如何在 bfs/dfs 搜索期间访问图中顶点的固有颜色(白色表示未触及,灰色表示已访问,黑色表示已完成)。 有人可以说明如何从 dfs/bfs 访问者中访问顶点的颜色吗?例如
当用户访问您的网站时,如何获取用户的信息? IP地址 苹果地址 用户个人资料名称 操作系统名称 操作系统版本 操作系统注册到(姓名/公司) 计算机名 浏览器名称 浏览器版本 ISP 名称/Intern
我最近开始使用 Amazon S3 为访问者提供图像,因为这会减少服务器负载。现在,出现了一个新问题:今天我查看了我的 AWS 账单。我注意到我有一大笔账单等着我——20 天内总共有 4TB 的 AW
session 劫持 所以我有一个小问题。我正在尝试识别访问者,这很难通过 $_SERVER veriables 来实现,如以下问题所述:Preventing session hijacking .
我有一个带有两个边定义的图,如下所示: isDepartment: [organisation] -> [organisation] hasAccess: [user] -> [organisatio
我是一名优秀的程序员,十分优秀!