【发布时间】:2011-12-14 18:03:38
【问题描述】:
不要被冗长的文字吓到,要点很简单,但需要一些代码来说明问题。 :-)
设置:
假设我想创建一个特征,这里建模为某种Converter,它本身是通用的,但有一个类型化的方法convert(),它返回一个适当类型化的结果对象,比如Container[T]:
trait Converter {
def convert[T]( input: T ) : Container[T]
}
trait Container[T] // details don't matter
我的问题是关于方法的类型约束,特别是对于强制平等,并且有两个密切相关的部分。
第 1 部分:现在说有一种特别适合基于数组的内容的专用容器类型,如下所示:
object Container {
trait ForArrays[U] extends Container[Array[U]]
}
鉴于这种可能性,我现在想将 Converter 特别是 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]
}
}
这样我就可以做这样的事情了:
val converter = new Converter.ForArrays { ... }
val input = Array( 'A', 'B', 'C' )
val converted : Container.ForArrays[Char] = converter.convert( input )
基本上,如果已知转换器的类型为Converter.ForArrays,我希望 Scala 也将convert[Char]() 的专用返回类型推断为Container.ForArrays[Char],即匹配的容器类型加上输入的数组类型。这是可能的吗?如果是这样,我该怎么做?例如。如何在 convert() 上指定类型参数/边界(所提供的只是一个替身——我不知道该怎么做)。哦,自然是这样它仍然会覆盖它的超级方法,否则什么也得不到。
第 2 部分: 作为后备,如果这不可能,我当然可以将 convert 函数向下推到以数组为中心的变体中,如下所示:
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]
}
}
好的。现在假设我有一个更专业的Converter.ForArrays.SetBased,它可以在内部使用一组 E 类型的元素(与“输入”数组元素类型相同)在转换期间执行一些特殊的魔法。然而,该集合现在是 trait 的一个参数,如下所示:
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] = {...}
}
再次,这是关于 convert() 方法的类型参数。这里的困难是:我如何将类的类型参数 - F - 与方法的类型参数 - E - 粘合在一起,这样 Scala 编译器只会让用户调用 convert() 并使用一个数组元素匹配集合的元素?示例:
val set = Set( 'X', 'Y', 'Z' )
val converter = new Converter.ForArrays.SetBased( set )
val input = Array( 'A', 'B', 'C' )
val converted : Container.ForArrays[Char] = converter.convert( input )
【问题讨论】:
标签: arrays scala types parameters type-bounds