0

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

我想做的是用一个方法组成一个类。该类有一个 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中允许这种嵌套使用泛型吗?

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 回答