9

我不明白为什么我得到“推断的类型参数不符合类型参数边界”。首先,我定义了一个称为 CS 的特征,它可以由多个类(例如 CS01 和 CS02)实现:

trait CS[+T <: CS[T]] {
  this: T =>
  def add: T
  def remove: T
}

class CS01 extends CS[CS01] {
  def add: CS01 = new CS01
  def remove: CS01 = new CS01
}

class CS02 extends CS[CS02] {
  def add: CS02 = new CS02
  def remove: CS02 = new CS02
}

add这个想法是在调用 CS01和removeCS02时保持实现的类型。其次,我想定义可以在每个符合 trait CS 的类上执行的操作。然后,我定义了一个名为的特征Exec(带有两个非常简单的类示例Exec01Exec02混合Exec特征):

trait Exec {
  def exec[U <: CS[U]](x: U): U
}

class Exec01 extends Exec {
  def exec[U <: CS[U]](x: U): U = x.add
}

class Exec02 extends Exec {
  def exec[U <: CS[U]](x: U): U = x.remove
}

再一次,我需要保留混合CS特征的类的实现类型。这就是为什么 exec 用[U <: CS[U]].

最后,我希望对它的任何CS启用操作都可以混合 trait Executable,从而可以执行 trait 之后的操作Exec

trait Executable[T <: CS[T]] {
  this: T =>
  def execute(e: Exec): T = e.exec(this)
}

但是,当我尝试编译时出现以下错误:

error: inferred type arguments [this.Executable[T] with T] do not conform to method exec's type parameter bounds [U <: this.CS[U]]
  def execute(e: Exec): T = e.exec(this)
                              ^

我不太明白,因为任何混合的类都Executable必须是T具有混合 CS 特征的约束的类型,因为trait Executable[T <: CS[T]]. 那么,为什么this不符合类型参数 boundU <: CS[U]呢?

4

2 回答 2

5

如果您明确指定要执行的类型参数,则有效:

def execute(e: Exec): T = e.exec[T](this)

似乎是类型推断的限制。

于 2013-01-11T14:38:37.540 回答
4

免责声明:这里不是 scala 大师,我在写这篇文章时正在学习它

首先,让我们简化示例。

scala> trait Moo[+X <: Moo[X]] 
defined trait Moo

scala> class Foo extends Moo[Foo]
defined class Foo

scala> def foobar[U <: Moo[U]](x: U) = x
foobar: [U <: Moo[U]](x: U)U

scala> foobar(new Foo)
res0: Foo = Foo@191275b

scala> class Bar extends Foo
defined class Bar

scala> foobar(new Bar)
<console>:12: error: inferred type arguments [Bar] do not conform to method 
foobar's type parameter bounds [U <: Moo[U]]
              foobar(new Bar)
              ^

scala> 

foobar接受一个Foo论点,但拒绝一个Bar只扩展的Foo。为什么?foobar是一个泛型,由其参数的类型参数化。它对该类型施加了限制。类型推断器不会检查参数类型的每一个祖先,希望找到一个满足界限的祖先。

那么如何对祖先类型施加界限呢?一种方法是使用存在类型。

scala> def foobar[V <: Moo[U] forSome {type U}](x: V) = x
foobar: [U <: Moo[_], V <: U](x: V)V

scala> foobar(new Foo)
res3: Foo = Foo@1154718

scala> foobar(new Bar)
res4: Bar = Bar@5a7ff7

scala> 
于 2013-01-11T14:13:10.480 回答