1

Scala の初心者として、SubClassing メソッドと Overriding メソッドのこの一見簡単な点に出くわしました。

私は Set を次のように特殊化しました。

    class SpecializedSet [T](s:Int, b: Boolean) (implicit ordering: Ordering [T]) extends TreeSet [T] { 
      override def + (t: T): SpecializedSet [T] = {

           if (this.isEmpty) {

              s = s + 1

              // I want to add an element to the Set
              super.+ (t) 

           }
           ....
       }

このクラスを使用するサイトでは、次のことを行います。

       class Driver {

         var e = new SpecializedSet [MyEarlierDefinedType](3,false);

         ......

         val elem1 = new MyEarlierDefinedType()

         e = e + eleme1 

         ......
     }

コンパイラはすぐに不平を言います:

型の不一致; 見つかった: scala.collection.immutable.TreeSet[T] 必須: org.personal.exercises.SpecializedSet[T]

オーバーライドされた '+' メソッドは 'SpecializedSet' 型 (サブタイプ) を返す必要があり、super.+() を呼び出すだけではそれが実現しないことを理解しています。

これは、super.+() が返す同じ TreeSet ではなく、代わりに作成された新しい TreeSet です。この新しい TreeSetを使用して、SpecializedSet() の新しいインスタンスを自分で作成する必要があると考えています。私はここで立ち往生しています。Supertype である TreeSet を使用して、新しい SpecializedSet() を作成するにはどうすればよいですか? そのような場合に使用する Scala の世界でのイディオムは何ですか? ここで asInstanceOf() の使用が最も適切で短い答えですか? しかし、その方法の使用はずっと推奨されていませんか?

apply() メソッドを定義する SpecializedSet のコンパニオン オブジェクトを作成する必要がありますか? あるいは、もっと深く掘り下げて、Scala で説明されている Traits の概念を使用する必要がありますか: レシーバーとサブクラスの実装型に型指定されたオブジェクトを返すメソッドを作成し、型とその他の関連リンクを返す方法を教えてください。または、 http://www.scala-lang.org/docu/files/collections-api/collections-impl.htmlのようにBuilderを作成するより複雑な方向に従ってください。

私もこの質問 (および回答) を調べました: Scala コレクションの拡張- これらは確かに便利です - しかし、どういうわけか、私が理解している以上のことがあると思います。たとえば、そのリンクの解決策の 1 つは、関数シグネチャで Baseclass の型を明示的に言及することです。

      override def + (t: T): TreeSet [T] = { // instead of SpecializedSet 
             ......

しかし、ある意味では、メソッドの呼び出し元の期待に反していませんか? 私は混乱しています。

これらのリンクで概説されているように、解決策はそれほど複雑である必要がありますか? 私が見逃している明らかな点は何ですか?どんなポインタでも役に立ちます。かなりの範囲を検索しましたが、私の質問が重複している場合は、ご容赦ください。

4

1 に答える 1

1

対応する特性を拡張し、直接継承ではなく構成を通じてクラスを使用したいと思います。

class SpecializedSet[T](s: Int, b: Boolean)(implicit ordering: Ordering[T]) extends SortedSet[T] {
  private var ts = new TreeSet[T]()
  override def +(t: T): SpecializedSet[T] = {
    ts += t
    this
  }
  override def -(t: T): SpecializedSet[T] = {
    ts -= t
    this
  }
  override def contains(t: T): Boolean = ts.contains(t)
  override def iterator(): Iterator[T] = ts.iterator
  override def ordering(): Ordering[T] = ts.ordering
  override def rangeImpl(from: Option[T], until: Option[T]) = ts.rangeImpl(from, until)
}

このアプローチは、クラスの直接継承と(直接の)スーパーへの呼び出しを回避するため、初心者にとってより使いやすいと思います。この非常に単純なソリューションの欠点は、可変性を導入したことです。これは、コンストラクターを少し再設計して、メンバーをaにし、の代わりに新しい変更されたインスタンスvalを実際に返すことができるようにすることで解決できます。SpecializedSetthis

于 2013-02-04T10:17:14.093 に答える