不要被长文本吓倒,这些要点非常琐碎,但需要一些代码来说明问题。 :-)
设置:
假设我想创建一个特征,这里建模为某种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]]
}
考虑到这种可能性,我现在想将转换器,特别是 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() 上的类型参数/界限(提供的只是一个替代 - 我不知道如何执行此操作)。哦,当然,这样它仍然重写它的 super 方法,否则什么也得不到。
第 2 部分:作为后备方案,如果这不可能,我当然可以将转换函数插入以数组为中心的变体中,如下所示:
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 类型的元素(与“输入”数组元素类型相同)在转换。然而,该集合现在是特征的参数,如下所示:
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 )
最佳答案
不,你不能。出于同样的原因,您在重写方法时不能缩小参数类型或扩大返回类型(但可以缩小返回类型)。不过,您可以执行以下操作(对于您的后备解决方案):
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 ) = ...
}
关于arrays - Scala:如何指定暗示相等的类型参数边界?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7886551/