2011-01-23 2 views
0

Это продолжение к this question.scala self-type: value не является составной ошибкой

Я пытаюсь реализовать векторы в Скале с общим суперкласса, используя само-типа:

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 
} 

Вот реализация 3D вектора:

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

Чтобы избавиться от всей гадости, вы должны указать, что параметр типа V является подклассом Vec. Теперь вы можете просто использовать 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.

+0

Спасибо. Я считаю, что это правильный ответ на мой первоначальный вопрос: http://stackoverflow.com/questions/4773611/proper-class-hierarchy-for-2d-and-3d-vectors. Не могли бы вы разместить там, чтобы я мог дать вам очки? – dsg

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]' vs. 'V'? Ответ на упомянутый вопрос (http://stackoverflow.com/questions/4774743/scala-self-type-member-of-type-parameter-error) был совершенно противоположным, измените тип возврата 'V' на' Vec [ V] '. – dsg

+1

Я думаю, что этот текущий вопрос не имеет ничего общего с sef-типами. 'normalize' просто вернет' Vec [V] 'и метод' cross' там не определен, но в вашей предыдущей версии '(this-v)' возвращает 'V', и в этом контексте' V' не считается 'Vec [V]' компилятором, потому что декларация самонастройки является однонаправленной (как указано в комментариях). – tenshi

Смежные вопросы