I often face the problem of wanting to add additional methods to classes I don't control. For instance, I might want to have a function prettyPrint
that can operate on different object types that do not have a unified api (e.g. special __str__
methods).
The Nice
language and R
accomplishes this using multimethods, which avoid the Visitor Pattern nicely. For instance, R
has the plot()
function. Individual programmers can create new classes to define data types (e.g., network graphs or stock ticker data). A secondary user/programmer could then write a plot function to fill out the functionality, even though they don't have access to the graph or stock ticker code, or the code of other plot functions.
Given that I would like to add lots of functionality later, using class.method()
seems infeasible. Lots of class_plot()
functions for each type also seems like a bad idea. Defining one big plot()
function that checks types isn't extensible.
What are alternatives to multimethods? In particular, I'm interested in designs that might work in Jython and Scala.
Easiest way to add a method to a class in Scala:
implicit def defSum(l: List[Double]): Double = new AnyRef { def sum = l.foldLeft(0.0)(_ + _) }
Or, on Scala 2.8, with the particular case of a method handling numbers,
implicit def defSum[T](l: List[T])(implicit n: Numeric[T]) = new AnyRef {
import n.mkNumericOps
def sum = l.foldLeft(n.zero)(_ + _)
}
Only this isn't needed on Scala 2.8, because it defines sum
already.
You can also add traits when instantiating:
// Immutable class
case class Point(x: Int, y: Int)
// Somewhere else in the code
trait MyPlot {
self: Point =>
import self._
def plot = println("At "+x+", "+y)
}
// Usage
val p = new Point(1,2) with MyPlot
p.plot
What you cannot do is add a method dynamically (ie, at run-time instead of compile-time) to an object. In the first case, you are saying "add this method to this class". On the second case you are saying "create this object with this trait". These are ok, but "add this method to this object" is not.
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