0

edit例を簡略化しました。詳細を追加しました。

私がやりたいのは、メソッドでクラスを構成することです。このクラスには、A[B] という形式の型パラメーターがあります。ここで、A と B は抽象型 (ジェネリック パラメーター) であり、そのメソッドは、型 A または B、または A または B から構成される他の型のオブジェクトを操作できます。たとえば、の場合、クラスには、A[B] 型オブジェクトをパラメーターとして受け取り、B 型オブジェクトを返すメソッドが含まれる場合があります。

この種のパターンは、たとえば C++ 標準テンプレート ライブラリでは非常に一般的です。

これはscalaで可能ですか?

以下の例では、ListDoer 内で、A は抽象型名 ListT であり、B は抽象型名 TElement です。後で、具象型 ListT[TElement] = MyList[Double] を提供しようとします。

class ListDoer[ ListT[TElement] ]
{
  // Processes abstract list type.                 
  def doIt( list:ListT[TElement] ) : TElement = { list.get(0) }   // TElement not found

  // Attempt 2:
  type L=ListT[TElement]               // TElement not found
  def doIt2( list:L ) : TElement ={ list.get(0) }   // TElement not found
}

// More concrete list type
class MyList[TElement]
{
   var None: TElement = _                         
   def get(i:Int): TElement = None   // placeholder               
   def put(i:Int, value:TElement): Unit = { }
}

// MyList[Double] is the concrete list type that doIt should take as a parameter
val doer2 = new ListDoer[ MyList[Double] ]   // MyList[Double] takes no parameters, expected one

val list1 = new MyList[Double]
doer2.doIt( list1 )         // Process list1. Should return list1.get(0)   

list.get(0) は、この例のプレースホルダー実装です。

ListDoer クラスは、型パラメーターとして提供されるもの以外の外部型を必要としません(たとえば、リストの特定の実装、または特定のコレクション ライブラリで指定されたインターフェイスに結び付けるべきではありません)。ただし、上記のコードでは、ListT[ElementT] にメソッド get(Int):ElementT が必要であり、これが満たされない場合、ListDoer のインスタンス化に失敗します。

上記のコードは (C++ のバックグラウンドを持っているため) 私には妥当に見えますが、次の 2 か所でコンパイルに失敗しています。

  • scala は、ListDoer 内のどこにも TElement という名前を見つけることができません。これにより、TElement を取得または返すメソッドを作成するのが難しくなります。

  • ListDoer をインスタンス化できません

scala で許可されているジェネリックのこの種のネストされた使用はありますか?

4

1 に答える 1

2
object XXX {

     class MyList[T] {
          var None: T = _
          def get(k: Int): T = None // placeholder               
          def put(k: Int, v: T): Unit = {}
     }

     class ListDoer[T] {

          // this defines the "wrapper" type 
          // which requires only get method to be there
          type W[T] = { def get(k: Int): T } 

          def doIt(list: W[T]): T = { 
               return null.asInstanceOf[T]
          } 
     }

     type L = Double
     val doer1 = new ListDoer[L] // L takes no parameters, expected one 
     val doer2 = new ListDoer[Double] // L takes no parameters, expected one

     val list1 = new MyList[Double]
     val list2 = List[L]()
     doer1.doIt(list1)

}
于 2013-08-12T22:51:07.177 に答える