不要被长篇文章拖延,这些要点非常简单,但需要一些代码来说明问题。 : - )
设置:
说我想创建一个特征,在这里建模为某种类型的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
答案 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.ForArrays
是Container
的子类,如果没有这个,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] = {...}
}