4

私はしばしば、自分が制御していないクラスにメソッドを追加したいという問題に直面します。たとえばprettyPrint、統一された API を持たないさまざまなオブジェクト タイプ (特殊な__str__メソッドなど) を操作できる関数が必要な場合があります。

このNice言語Rは、ビジター パターンを適切に回避するマルチメソッドを使用してこれを実現します。たとえばR、機能がありplot()ます。個々のプログラマーは、新しいクラスを作成してデータ型 (ネットワーク グラフや株価情報データなど) を定義できます。二次的なユーザー/プログラマーは、グラフや株式ティッカー コード、または他のプロット関数のコードにアクセスできない場合でも、プロット関数を記述して機能を埋めることができます。

後で多くの機能を追加したいことを考えると、使用class.method()は不可能に思えます。class_plot()型ごとにたくさんの関数を用意するのも悪い考えのようです。型をチェックする 1 つの大きなplot()関数を定義することは拡張できません。

マルチメソッドの代替手段は何ですか? 特に、Jython と Scala で動作する可能性のあるデザインに興味があります。

4

4 に答える 4

7

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)(_ + _)
}

sumこれだけは既に定義されているため、Scala 2.8 では必要ありません。

インスタンス化時に特性を追加することもできます:

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

オブジェクトにメソッドを動的に (つまり、コンパイル時ではなく実行時に) 追加することはできません。最初のケースでは、「このメソッドをこのクラスに追加する」と言っています。2番目のケースでは、「この特性でこのオブジェクトを作成する」と言っています。これらは問題ありませんが、「このメソッドをこのオブジェクトに追加する」はそうではありません。

于 2009-08-24T22:00:41.630 に答える
1

自分でマルチメソッドを実装したくない場合は、 Python用のマルチメソッドのパッケージ化された実装があります。Jythonでも動作することを期待しています。

もう1つのオプションは、マルチメソッドが組み込まれているClojureをチェックアウトすることです。

于 2009-08-25T07:29:31.447 に答える
1

Python と Jython では mixin クラスが許可されているため、それらを使用して「拡張」メソッドを保持できます。

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

明らかに、さまざまなタイプのメソッドのホストがplot必要な場合は、どこかに実装が必要です。これにより、複数の mixin クラスが発生する可能性があります。別の方法は、キーが型で値が関数 (または関数のセット) である辞書を使用することです。この回答を参照してください。

また、クラスにモンキーパッチを適用したくないと想定していますが、これも技術的には可能です (ただし、お勧めできません)。

于 2009-08-24T19:56:44.187 に答える
1

Scala にはImplicitsの概念があります。これは、C# の拡張メソッドとの類似性です。

于 2009-08-24T20:04:36.590 に答える