不要被冗长的文字吓到,这些要点很简单,但需要一些代码来说明问题。:-)
设置:
假设我想创建一个特征,这里被建模为Converter
某种类型的,它本身是通用的,但有一个类型化的方法convert()
,它返回一个适当类型化的结果对象,比如 a 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 )
基本上我希望 Scala,如果已知转换器的类型是,也可以推断出asConverter.ForArrays
的专门返回类型,即匹配的容器类型加上输入的数组类型。这是可能的吗?如果是这样,我该怎么做?例如,我如何在 convert() 上指定类型参数/边界(提供的只是一个替身——我不知道该怎么做)。哦,当然它仍然会覆盖它的超级方法,否则什么也得不到。convert[Char]()
Container.ForArrays[Char]
第 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 )