Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the drawbacks of writing an algorithm in a class or in an object (in Scala)?

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

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

In which circumstances should the class be used and in which should the object be used (for implementing an algorithm, e.g. Dijkstra-Algorithm, as shown above) ?

Which criterias should be considered when making such a decision ?

At the moment, I can not really see what the beneftis of using a class are.

like image 348
John Threepwood Avatar asked Dec 21 '22 19:12

John Threepwood


2 Answers

If you only have one implementation, this can largely be a judgement call. You mentioned Dijkstra's algorithm, which runs on a graph. Now you can write that algorithm to take a graph object as an explicit parameter. In that case, the algorithm would presumably appear in the Graph singleton object. Then it might be called as something like Graph.shortestPath(myGraph,fromNode,toNode).

Or you can write the algorithm in the Graph class, in which case it no longer takes the graph as an explicit parameter. Now it is called as something like myGraph.shortestPath(fromNode,toNode).

The latter case probably makes more sense when there is one main argument (eg, the graph), especially one that serves as a kind of context for the algorithm. But it may come down to which syntax you prefer.

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. For example, you might have two different implementations of shortestPath, one that works better on adjacency matrices and one that works better on adjacency lists. With the class approach, you can easily have two different graph classes for the two different representations, and each can have its own implementation of shortestPath. Then, when you call myGraph.shortestPath(fromNode,toNode), you automatically get the right implementation, even if you don't know whether myGraph uses adjacency matrices or adjacency lists. (This is kind of the whole point of OO.)

like image 160
Chris Okasaki Avatar answered Jan 17 '23 14:01

Chris Okasaki


Classes can have subclasses which override implementation, objects cannot be subclassed. Classes can also be type parametric where objects cannot be.

There's only ever one instance of the object, or at least one instance per container. A class has multiple instances. That means that the class can be parameterized with values

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

And that can be reused like

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

To bring all this home relative to your example of Djikstra's algorithm: imagine you want to write one implementation of the algorithm that is reusable across multiple node types. Then you might want to parameterize by the Node type, the type of metric used to measure distance, and the function used to calculate distance.

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

You create one instance of Djikstra per distinct type of node/metric/distance function that you use in your program and reuse that instance without having to pass all that information in everytime you compute Djikstra.

In summary, classes are more flexible. Use them when you need the flexibility. Otherwise objects are fine.

like image 31
James Iry Avatar answered Jan 17 '23 14:01

James Iry