我在Scala中有一个通用的F-bounded特性。让我写一些返回相同底层实现类型的方法,超级!但现在让我们说一个子特征也定义需要F边界的方法。 Scala正在向我发回没有意义的编译错误:
package sandbox
import sandbox.ComplexImpl.AnyComplexImpl
import scala.language.existentials
trait FBounded[IMPL <: FBounded[IMPL]] { self: IMPL =>
def foo: IMPL
}
trait FBoundedUser[F <: FBounded[F]] {
def bar(value: F): F = value.foo
}
trait SimpleImpl extends FBounded[SimpleImpl] {
override def foo: SimpleImpl = this
}
object SimpleUser extends FBoundedUser[SimpleImpl]
// A-OK so far...
trait ComplexImpl[IMPL <: ComplexImpl[IMPL]] extends FBounded[IMPL] { self: IMPL =>
def baz: IMPL
}
object ComplexImpl {
type AnyComplexImpl = ComplexImpl[T] forSome { type T <: ComplexImpl[T] }
}
object ComplexUser1 extends FBoundedUser[ComplexImpl[_]]
object ComplexUser2 extends FBoundedUser[AnyComplexImpl]
尝试使用ComplexUser1
或ComplexUser2
进行编译会导致:
Error:(32, 29) type arguments [sandbox.ComplexImpl.AnyComplexImpl] do not conform to trait
FBoundedUser's type parameter bounds [F <: sandbox.FBounded[F]]
这对我没有意义。 AnyComplexImpl
肯定会实现FBounded
。我错过了什么,或者类型检查器让我失败了吗?
编辑:
class Concrete() extends ComplexImpl[Concrete] {
override def baz: Concrete = this
override def foo: Concrete = this
}
object ComplexUser3 extends FBoundedUser[Concrete]
编译得很好。那么为什么不通用版呢?
答案 0 :(得分:1)
约束要求AnyComplexImpl
实施FBounded[AnyComplexImpl]
,它不是FBounded[T] forSome { type T <: ComplexImpl[T] }
。
如果你使FBounded
和ComplexImpl
协变,那么它就有效。编译器的原因是:
AnyComplexImpl
是任何ComplexImpl[T]
的超类型,其中T <: ComplexImpl[T]
;
因此FBounded[T] forSome { type T <: ComplexImpl[T] }
是FBounded[AnyComplexImpl]
的子类型;
因此AnyComplexImpl
是FBounded[AnyComplexImpl]
的子类型。
但我怀疑尝试混合F-bounded类型和存在可能会导致其他问题。 ComplexUser1
和ComplexUser2
编译的原因恰恰在于它们不是通用的。请考虑使用实际的通用版本:
def complexUser4[T <: ComplexImpl[T]] = new FBoundedUser[T] {}