为什么trait方法需要asInstanceOf和class方法不需要

时间:2012-07-23 05:33:08

标签: scala generics traits

我定义了以下特征:

trait Felem[T <: Felem[T]] {                                               
  def mul(that: T): T
  def square: T = this.mul(this.asInstanceOf[T])                            
}

我还根据这个特性定义了一个类:

class F2elem(val coef: Boolean) extends Felem[F2elem] {
  override def square: F2elem = this.mul(this)
  ...
}

我的问题是关于特征中“square”方法定义中“asInstanceOf”的需要。如果我删除它,我会收到以下错误:

error: type mismatch;
found   : Felem.this.type (with underlying type Felem[T])
required: T
def square: T = this.mul(this)
  1. 为什么需要特质?
  2. 为什么课堂上不需要它?
  3. 在执行时间或内存方面是否需要花费任何费用?

3 个答案:

答案 0 :(得分:7)

mult的参数必须是T类型。

调用mul(this)时,此参数的类型为Felem[T],该参数不符合T且不符合TFelem[T]符合Felem[T]的附加约束。但这不是你想要的,你需要相反的,T符合F2elem

另一方面,在T中,F2elem正好是Felem,所以它是一个类型(完全无关,一个是特质而另一个是一个类)

以下示例显示Felem[T]中的定义确实不能进行类型检查,并且可能存在T不符合class F3elem extends Felem[F2elem] // this is 2, not 3 的实现者。

F2elem

此声明是正确的,为T提供的T <: Felem[T]满足his.mul(this)。 但是,square中的继承t T将无效,mult期望F2elem,即F3elem,这是Felem。他们是无关的。

您可能希望每个F2elem必须与T类似,即trait Felem [T <: Felem[T]] { this: T => /* your code */ } 必须是实际类的类型。您可以使用自我类型强制执行此操作。

T

当您编写它时,您声明在每个实现中,实现的类型必须符合{{1}}。这样做,它会进行类型检查,并且你不会被允许在上面实现F3elem:

  

错误:非法继承;自我型F3elem不符合   Felem [F2elem]的自我型F2elem          F3elem课程扩展了Felem [F2elem] {

答案 1 :(得分:2)

1)在trait this中,T不是scala> trait Felem[T <: Felem[T]] { | def mul(that: T): T = that | def square: T = this.mul(this.asInstanceOf[T]) | } defined trait Felem scala> class F2elem extends Felem[F2elem] defined class F2elem scala> class F3elem extends Felem[F2elem] defined class F3elem scala> new F3elem() res1: F3elem = F3elem@2e0b08f1 scala> res1.square java.lang.ClassCastException: F3elem cannot be cast to F2elem 的实例:

class

2)在this F2elem TF2elem == thisT为{{1}}。

答案 2 :(得分:1)

您使用T作为方法的参数类型。这意味着无论T的类型是什么类型都是方法中所需的类型(因此不需要类中的强制转换,因为它的类型最初由T表示)。

如果您将that的类型更改为Felem[T],则不需要演员。