Альтернативы мультиметодам в Scala или Jython - PullRequest
4 голосов
/ 24 августа 2009

Я часто сталкиваюсь с проблемой желания добавить дополнительные методы в классы, которые я не контролирую. Например, я мог бы хотеть иметь функцию prettyPrint, которая может работать с различными типами объектов, которые не имеют унифицированного API (например, специальные __str__ методы).

Язык Nice и R выполняют это с помощью мультиметодов, которые прекрасно обходят Шаблон посетителя. Например, R имеет функцию plot(). Отдельные программисты могут создавать новые классы для определения типов данных (например, сетевых графиков или данных биржевых сводок). Затем вторичный пользователь / программист может написать функцию построения графика, чтобы заполнить функциональность, даже если у него нет доступа к графику, коду биржевого тикера или коду других функций построения графика.

Учитывая, что я хотел бы добавить много функциональности позже, использование class.method() кажется невозможным. Многие функции class_plot() для каждого типа также кажутся плохой идеей. Определение одной большой plot() функции, которая проверяет типы, не является расширяемым.

Какие есть альтернативы мультиметодам? В частности, мне интересны проекты, которые могут работать в Jython и Scala.

Ответы [ 4 ]

7 голосов
/ 25 августа 2009

Самый простой способ добавить метод в класс в Scala:

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

Или, в Scala 2.8, с частным случаем обработки чисел методом,

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

Только это не требуется в Scala 2.8, поскольку оно уже определяет sum.

Вы также можете добавить черты при создании экземпляра:

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

То, что вы не можете сделать, это динамически добавить метод (т. Е. Во время выполнения вместо времени компиляции) к объекту. В первом случае вы говорите «добавить этот метод в этот класс». Во втором случае вы говорите «создайте этот объект с этой чертой». Это нормально, но «добавить этот метод к этому объекту» нельзя.

1 голос
/ 25 августа 2009

Если вы не хотите реализовывать мультиметоды самостоятельно , существует пакетная реализация мультиметодов для Python. Я ожидаю, что это работает и на Jython.

Другой вариант - проверить Clojure , в котором есть встроенные мультиметоды .

1 голос
/ 25 августа 2009
1 голос
/ 24 августа 2009

Python и Jython допускают смешанные классы, так что вы можете использовать их для хранения ваших "расширенных" методов:

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

Очевидно, что если вам нужен хост plot методов для разных типов, то вам нужно где-то иметь реализации - это может привести к нескольким классам смешивания. Альтернативой является использование словаря, в котором ключом является тип, а значением является функция (или набор функций): см. этот ответ .

Я также предполагаю, что вы не хотите использовать классы-патчи, что также технически возможно (хотя и нежелательно).

...