2

私は Scala の初心者なので、これがばかげた質問であれば許してください。

追加のメソッドを含む拡張 Map タイプを作成したいとします。これを行う方法はいくつかあります。1つ目は構成です:

class Path[V](val m: Map[V, Int]) {
  // Define my methods
}

もう1つは継承によるものです。

class Path[V] extends Map[V, Int] {
// Define my methods
}

最後に、「特性」ルートも検討しました。

trait Path[V] extends Map[V, Int] {
// Define my methods
}

内部のものを常に参照する必要があるため、構成は少し厄介です。継承はかなり自然ですが、私にはしわがあります (詳細は後ほど)。Traits はこれを行うための非常にエレガントな方法のように思えます。「with」構造を使用するのは非常に便利ですが、私にとっては問題もあります。

私が遭遇しているしわは、++のようなメソッドにあります。彼らは新しい地図を返します。したがって、上記の「私の方法」がマップに何かを追加したいとしましょう(単なる例です。マップには既にこれがあることがわかっています)。

trait Path[V] extends Map[V,Int] {
    def addOne(v: V, i: Int): Path[V] = this + (v -> i)
}

戻り値の型が Path[V] ではないため、これはエラーを生成します。これで、新しいインスタンスで "with" を使用して Path[V] トレイトを追加できることがわかりました。しかし、ここで新しいマップの構築を制御することはできません。Path[V] トレイトを追加する方法はありますか? 事前入力された新しい不変マップを作成し、「with Path[V]」でタグ付けすることを考えましたが、事前入力されたマップを作成するために使用できるコンストラクターはありません。

継承を使用して同様の問題が発生するのではないかと思います (確認はしていませんが)。マップに新しいエントリを追加する新しいメソッドを追加することはできますが、必要な "Path[V]" を取得できません。合成アプローチは、ここに行く唯一の方法のようです。

これが明確であることを願っています。コメント?

4

1 に答える 1

6

おそらくこれを行う最も簡単な方法は、MapProxy特性を使用することです:

import collection._

class Path[V](val self: Map[V, Int]) extends MapProxy[V, Int] {
   // without the companion object below
   def addOne(v: V, i: Int): Path[V] = new Path(this + (v -> i))
   // with the companion object below
   def addOne(v: V, i: Int): Path[V] = this + (v -> i)
   // other methods
}

// this companion object is not strictly necessary, but is useful:
object Path {
   implicit def map2path[V](map: Map[V, Int]): Path[V] = new Path(map)
}

Pathこれにより、 a を aであるかのように扱うことができるため、合成アプローチの扱いにくさを解消できますMap

scala> new Path(Map("a" -> 1)) + ("b" -> 2)
res1: scala.collection.Map[java.lang.String,Int] = Map((a,1), (b,2))

scala> new Path(Map("a" -> 1)).get("a")
res2: Option[Int] = Some(1)

Mapからへの暗黙的な変換Path(コンパニオン オブジェクトで定義) を含めると、 aを であるかPathのように扱うこともできます。MapPath

scala> Map("a" -> 1).addOne("b", 2)
res3: Path[java.lang.String] = Map((a,1), (b,2))

に動作を追加するための同様のSeqProxy特性がありSeqます。

より一般的なケースでは、解決策はpimp my library patternを使用することです。この関連する質問には例があります。

于 2010-08-12T22:40:45.603 に答える