4
class A {
  def algorithmImplementation (...) = { ... }
}

object A {
  def algorithmImplementation (...) = { ... }
}

应该在哪些情况下class使用以及应该在哪些情况下object使用(用于实现算法,例如 Dijkstra-Algorithm,如上所示)?

做出此类决定时应考虑哪些标准?

目前,我真的看不出使用 aclass有什么好处。

4

2 回答 2

6

如果您只有一个实现,这在很大程度上可能是一个判断电话。你提到了 Dijkstra 的算法,它在图上运行。现在您可以编写该算法以将图形对象作为显式参数。在这种情况下,该算法可能会出现在 Graph 单例对象中。然后它可能被称为 Graph.shortestPath(myGraph,fromNode,toNode)。

或者您可以在 Graph 类中编写算法,在这种情况下,它不再将图形作为显式参数。现在它被称为 myGraph.shortestPath(fromNode,toNode)。

当有一个主要参数(例如,图形)时,后一种情况可能更有意义,尤其是作为算法的一种上下文的参数。但这可能归结为您喜欢哪种语法。

However, if you have multiple implementations, the balance tips more toward the class approach, especially when the choice of which implementation is better depends on the choice of representation. 例如,您可能有两种不同的 shortestPath 实现,一种在邻接矩阵上效果更好,另一种在邻接列表上效果更好。使用类方法,您可以轻松地为两种不同的表示形式创建两个不同的图类,并且每个类都可以有自己的最短路径实现。然后,当您调用 myGraph.shortestPath(fromNode,toNode) 时,您会自动获得正确的实现,即使您不知道 myGraph 是使用邻接矩阵还是邻接列表。(这就是 OO 的重点。)

于 2012-06-26T13:40:45.320 回答
5

类可以有覆盖实现的子类,对象不能被子类化。类也可以是类型参数,而对象不能。

该对象只有一个实例,或者每个容器至少有一个实例。一个类有多个实例。这意味着可以使用值对类进行参数化

class A(param1 : int, param2 : int) {
    def algorithmImplementation(arg : List[String]) = // use arg and params
}

这可以像这样重复使用

val A42_13 = new A(42, 13)
val result1 = A42_13.algorithmImplementation(List("hello", "world"))
val result2 = A42_13.algorithmImplementation(List("goodbye", "cruel", "world"))

将所有这些与您的 Djikstra 算法示例相关联:假设您想要编写一个可跨多种节点类型重用的算法实现。然后,您可能希望按节点类型、用于测量距离的度量类型以及用于计算距离的函数进行参数化。

val Djikstra[Node, Metric <: Comparable[Metric]](distance : (Node, Node) => Metric) {
    def compute(node : Node, nodes : Seq[Node]) : Seq[Metric] = {...}
}

您为程序中使用的每种不同类型的节点/度量/距离函数创建一个 Djikstra 实例,并重用该实例,而无需在每次计算 Djikstra 时传递所有这些信息。

总之,类更灵活。当您需要灵活性时使用它们。否则对象很好。

于 2012-06-26T13:48:37.810 回答