简体   繁体   English

为什么特质方法需要asInstanceOf而类方法不需要

[英]why trait method needs asInstanceOf and class method don't

I have defined the following trait: 我定义了以下特征:

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

I also define a class based on this trait: 我还基于此特征定义了一个类:

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

My questions are about the need of "asInstanceOf" in the definition of the "square" method in the trait. 我的问题是有关特征中“ square”方法的定义中是否需要“ asInstanceOf”的。 If I remove it, I get the following error: 如果删除它,则会出现以下错误:

error: type mismatch;
found   : Felem.this.type (with underlying type Felem[T])
required: T
def square: T = this.mul(this)
  1. Why is it needed in the trait ? 为什么特质需要它?
  2. Why it is not needed in the class ? 为什么在课堂上不需要它?
  3. Does it cost anything in term of execution time or memory ? 就执行时间或内存而言,它会花费什么吗?

The parameter of mult must be of type T . 参数mult必须为T类型。

When calling mul(this) , the this parameter is of type Felem[T] , which is not and does not conform to T . 调用mul(this) ,this参数的类型为Felem[T] ,该参数不是T且不符合T There is the additional constraint that T conforms to Felem[T] . 还有一个附加约束条件,即T符合Felem[T] But this is not what you want, you would need the opposite, Felem[T] to conform to T . 但这不是您想要的,您需要相反的Felem[T]来符合T

On the other hand, in F2elem , T is exactly F2elem , so it typechecks (completley unrelated to one being a trait and the other one a class) 另一方面,在F2elemT恰好是F2elem ,因此它进行类型检查(与一个无关的完全性是一个特征,另一个完全无关)。

Here is example to show that the definition in Felem must indeed not typecheck, and that it is possible to have implementors where Felem[T] does not conform to T . 这是一个示例,说明Felem中的定义确实不能进行类型检查,并且可能有Felem[T]不符合T

class F3elem extends Felem[F2elem] // this is 2, not 3

This declaration is correct, F2elem which is given for T satisfies T <: Felem[T] . 这个声明是正确的,为T给出的F2elem满足T <: Felem[T] However, an inherited t his.mul(this) in square would be invalid, mult expect a T , that is F2elem , and this is F3elem . 但是,以square继承的t his.mul(this)将是无效的,多期待一个T ,即F2elem ,这是F3elem And they are unrelated. 它们是无关的。

What you probably want is that every Felem must be like F2elem , that is that T must be the type of the actual class. 您可能想要的是每个Felem必须像F2elem一样,也就是说T必须是实际类的类型。 You can enforce this with a self type. 您可以使用自我类型来强制实施。

trait Felem [T <: Felem[T]] { this: T => /* your code */ }

When you write that, you state that in every implementation, the type of the implementation must conform to T . 在编写该代码时,您要声明在每个实现中,实现的类型必须符合T Doing that, it will typecheck, and you will not be allowed to instanciate F3elem above : 这样做,它将进行类型检查,并且您将无法实例化上面的F3elem:

error: illegal inheritance; 错误:非法继承; self-type F3elem does not conform to Felem[F2elem]'s selftype F2elem class F3elem extends Felem[F2elem] { 自类型F3elem不符合Felem [F2elem]的自类型F2elem类F3elem扩展了Felem [F2elem] {

1) In your trait this is not an instance of T : 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

2) In your class this is F2elem and T == F2elem , so this is T . 2)在您的class thisF2elemT == F2elem ,所以thisT

You're using T as your method's parameter type. 您正在使用T作为方法的参数类型。 This means that whatever the type of T is will be the type that's required in the method (hence not needing the cast in the class, since its type is what is signified by T originally). 这意味着无论T的类型是方法中所需的类型(因此不需要在类中进行强制转换,因为它的类型最初是T表示的)。

If you change the type of that to Felem[T] , you will not need the cast. 如果更改的类型thatFelem[T]你不需要投。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM