2009-08-24 10 views
4

Ich habe oft das Problem, dass ich zusätzliche Methoden zu Klassen hinzufügen möchte, die ich nicht kontrolliere. Ich möchte zum Beispiel eine Funktion prettyPrint haben, die auf verschiedenen Objekttypen arbeiten kann, die keine vereinheitlichte API haben (z. B. spezielle __str__ Methoden).Alternativen zu Multimethoden in Scala oder Jython

Die Nice Sprache und R erreicht dies mit Multimethoden, die das Besucher-Muster schön vermeiden. Zum Beispiel hat R die plot() Funktion. Individuelle Programmierer können neue Klassen erstellen, um Datentypen zu definieren (z. B. Netzwerkgraphen oder Börsentickerdaten). Ein sekundärer Benutzer/Programmierer könnte dann eine Plot-Funktion schreiben, um die Funktionalität auszufüllen, auch wenn sie keinen Zugriff auf den Graphen- oder Aktien-Ticker-Code oder den Code anderer Plot-Funktionen haben.

Vorausgesetzt, dass ich später viele Funktionen hinzufügen möchten, scheint die Verwendung class.method() undurchführbar. Viele class_plot() Funktionen für jeden Typ scheint auch eine schlechte Idee. Definieren einer großen plot()-Funktion, die Typen prüft, ist nicht erweiterbar.

Was sind Alternativen zu Multimethoden? Insbesondere interessieren mich Designs, die in Jython und Scala funktionieren könnten.

Antwort

7

Der einfachste Weg, eine Methode zu einer Klasse in Scala hinzuzufügen:

implicit def defSum(l: List[Double]): Double = new AnyRef { def sum = l.foldLeft(0.0)(_ + _) } 

Oder auf Scala 2.8, mit dem besonderen Fall eines Verfahrens zum Umgang mit Zahlen,

implicit def defSum[T](l: List[T])(implicit n: Numeric[T]) = new AnyRef { 
    import n.mkNumericOps 
    def sum = l.foldLeft(n.zero)(_ + _) 
} 

Nur dieses isn‘ t benötigt auf Scala 2.8, weil es bereits sum definiert.

Sie können auch Merkmale hinzufügen, wenn instanziieren:

// 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 

Was Sie können eine Methode dynamisch nicht tun ist hinzuzufügen (dh zur Laufzeit statt der Kompilierung Zeit) an einem Objekt. Im ersten Fall sagen Sie "Fügen Sie diese Methode zu dieser Klasse hinzu". Im zweiten Fall sagen Sie "Erzeuge dieses Objekt mit diesem Merkmal". Diese sind in Ordnung, aber "diese Methode zu diesem Objekt hinzufügen" ist nicht.

1

Python und Jython mixin Klassen ermöglichen, so dass Sie diese verwenden können, um „Erweiterung“ Methoden zu halten:

class Derived(Base, Mixin1, Mixin2, ...): 
    ... 

Klar, wenn Sie eine Vielzahl von plot Methoden für unterschiedliche Typen wollen, dann müssen Sie Implementierungen irgendwo haben - Dies könnte zu mehreren Mixinklassen führen. Eine Alternative besteht darin, ein Wörterbuch zu verwenden, bei dem der Schlüssel der Typ und der Wert die Funktion (oder der Satz von Funktionen) ist: siehe this answer.

Ich gehe auch davon aus, dass du keine affe-patch-klassen möchtest, was auch technisch möglich ist (wenn auch nicht ratsam).