2011-01-23 55 views
0

这是this question的后续行动。斯卡拉自我类型:值不是一个成员错误

我试图使用自类型来实施阶向量与通用超类:

trait Vec[V] { self:V => 
    def /(d:Double):Vec[V] 
    def dot(v:V):Double 

    def norm:Double = math.sqrt(this dot this) 
    def normalize = self/norm 
} 

这里是一个三维向量的实现:

class Vec3(val x:Double, val y:Double, val z:Double) extends Vec[Vec3] 
{ 
    def /(d:Double) = new Vec3(x/d, y/d, z/d) 
    def dot(v:Vec3) = x * v.x + y * v.y + z * v.z 
    def cross(v:Vec3):Vec3 = 
    { 
     val (a, b, c) = (v.x, v.y, v.z) 
     new Vec3(c * y - b * z, a * z - c * x, b * x - a * y) 
    } 

    def perpTo(v:Vec3) = (this.normalize).cross(v.normalize) 
} 

不幸的是,这并不编译:

Vec3.scala:10: error: value cross is not a member of Vec[Vec3] 
    def perpTo(v:Vec3) = (this.normalize).cross(v.normalize) 
             ^

怎么回事,我该如何解决?

此外,任何关于自我类型的参考将不胜感激,因为我认为这些错误是由于我缺乏理解而出现的。

回答

8

为了摆脱在所有这些糟糕的事情中,你必须指定类型参数VVec的子类。 现在你可以随处使用V,因为你的特质知道V继承了所有的Vec[V]方法。

trait Vec[V <: Vec[V]] { self: V => 
    def -(v:V): V 
    def /(d:Double): V 
    def dot(v:V): Double 

    def norm:Double = math.sqrt(this dot this) 
    def normalize: V = self/norm 
    def dist(v: V) = (self - v).norm 
    def nasty(v: V) = (self/norm).norm 
} 

注意方法nasty这不会Easy Angel’s approach编译。

3

我认为,这种方法/Vec应该返回V而不是Vec[V]

trait Vec[V] { self:V => 
    def /(d:Double): V 
    def dot(v:V):Double 

    def norm:Double = math.sqrt(this dot this) 
    def normalize = self/norm 
} 

方法的横在Vec3存在(或者换句话说,在V),但不是在Vec[V]

+0

什么时候使用`Vec [V]`与`V`的经验法则?引用问题的答案(http://stackoverflow.com/questions/4774743/scala-self-type-member-of-type-parameter-error)恰恰相反,将返回类型`V`更改为`Vec [ V]`。 – dsg 2011-01-23 22:34:19

+1

我认为这个问题与sef-types没有任何关系。 `normalize`只会返回`Vec [V]`并且方法`cross`没有在那里定义,但是在你之前的问题中`(this-v)`返回`V`,在这种情况下`V`不被认为是因为自我类型的声明是单向的(正如评论中所提到的那样),所以由Compiller提供`Vec [V]`。 – tenshi 2011-01-23 22:52:20

相关问题