Scala:如何指定隐含相等的类型参数边界?

时间:2011-10-25 08:24:17

标签: arrays scala types parameters type-bounds

不要被长篇文章拖延,这些要点非常简单,但需要一些代码来说明问题。 : - )

设置:

说我想创建一个特征,在这里建模为某种类型的Converter,它本身是通用的,但有一个类型化的方法convert(),它返回一个适当类型的结果对象,比如一个{ {1}}:

Container[T]

我的问题是关于方法的类型限制,特别是对于实施平等,并且有两个密切相关的部分。

第1部分:现在假设有一种特殊的容器类型特别适合基于数组的内容,如下所示:

 trait Converter {
   def convert[T]( input: T ) : Container[T]
 } 
 trait Container[T]  // details don't matter

鉴于这种可能性,我现在想将转换器,特别是 object Container { trait ForArrays[U] extends Container[Array[U]] } 方法的返回类型专门化为专门的convert()类型:

Container.ForArrays

所以我可以这样做:

 object Converter {
   trait ForArrays extends Converter {
     // the following line is rubbish - how to do this right?
     def convert[E,T <: Array[E]]( input: T ) : Container.ForArrays[E]
   } 
 }

基本上我想要Scala,如果已知转换器类型为val converter = new Converter.ForArrays { ... } val input = Array( 'A', 'B', 'C' ) val converted : Container.ForArrays[Char] = converter.convert( input ) ,还要将Converter.ForArrays的专用返回类型推断为convert[Char](),即匹配的容器类型加上数组类型的输入。是这样还是类似的事情,如果是这样,我该怎么做?例如。如何在convert()上指定类型参数/边界(提供的只是一个替身 - 我不知道如何做到这一点)。哦,当然它仍然会超越它的超级方法,否则什么都得不到。

第2部分:作为后备,如果这不可能,我当然可以将转换功能推送到以阵列为中心的变体中,如下所示:

Container.ForArrays[Char]

行。现在说我有一个更专业的 trait Converter // now pretty useless as a shared trait object Converter { trait ForValues extends Converter { def convert[T]( input: T ) : Container[T] } trait ForArrays extends Converter { def convert[E]( input: Array[E] ) : Container.ForArrays[E] } } ,它可以在内部使用一组E类元素(与'input'数组元素类型相同)在转换过程中做一些特殊的魔术。该集合现在是特征的参数,但是,如下所示:

Converter.ForArrays.SetBased

同样,这是关于convert()方法的类型参数。这里的困难是:如何将类的类型参数 - case class SetBased( set: Set[F] ) extends Converter.ForArrays { // the following line is also rubbish... def convert[E = F]( input: Array[E] ) : Container.ForArrays[E] = {...} } - 粘贴到方法的类型参数 - F - 这样Scala编译器只会让用户调用{{1一个数组的元素与集合的元素匹配?示例:

E

2 个答案:

答案 0 :(得分:4)

不,你不能。出于同样的原因,在覆盖方法时不能缩小参数类型或扩展返回类型(但可以缩小返回类型)。这是你可以做的,但是(对于你的后备解决方案):

trait Converter {
  type Constraint[T]
} 

trait ForArrays extends Converter {
  def convert[E]( input: Array[E] )( implicit ev : Constraint[T] ) : Container.ForArrays[E]
}

case class SetBased[F](set: Set[F]) extends Converter {
   type Constraint[T] = T =:= F
   def convert[E]( input: Array[E] )( implicit ev : E =:= F ) = ...
} 

答案 1 :(得分:1)

我将假设Container.ForArraysContainer的子类,如果没有这个,Converter.ForArrays.convert将不会匹配被覆盖的Converter.convert的签名

尝试写下这样的内容:

object Converter {
  trait ForArrays extends Converter {
    def convert[E] (input: Array[E]): Container.ForArrays[E]
  } 
}

关于您的后备解决方案。如果两种类型相同,那么只需使用相同类型的参数!

case class SetBased (set: Set[F]) extends Converter.ForArrays {
  def convert (input: Array[F]): Container.ForArrays[F] = {...}
}