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.
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.)
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With