如何在scala中使用嵌套泛型

时间:2013-08-12 22:24:02

标签: scala

编辑简化示例。添加了更多细节。

我想要做的是用一个方法组成一个类。该类具有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 ++背景),但无法在两个地方编译:

  • scala无法在ListDoer中的任何位置看到名称TElement。这使得制作或返回TElement

  • 的方法变得困难
  • 无法实例化ListDoer

scala中允许这种嵌套使用泛型吗?

1 个答案:

答案 0 :(得分: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)

}