Подтвердить что ты не робот

Как использовать черту scala с ссылкой `self`?

Я видел некоторую черту записи кода следующим образом:

trait SelfAware { self: Self =>
 ....
}

class Self
val s = new Self with SelfAware // this is ok
println(s.self) // error happened

class X
new X with SelfAware // error happened here

Я хотел бы знать, почему произошла ошибка и как использовать черту таким образом?

4b9b3361

Ответ 1

Ошибка возникает, потому что вы ограничили тип ссылки this (которую вы назвали self) имеют тип self. Когда вы говорите new Self with SelfAware, это нормально, потому что этот объект имеет тип self, как вы просили. Но когда вы говорите new X with SelfAware, нет никаких доказательств того, что X каким-либо образом является подтипом self.

В вашем новом объекте типа X with SelfAware, каким будет его член self? Ну, это не было бы типа self, а типа X. Но вы определили черту SelfAware, так что self должен иметь тип self, поэтому вы получаете ошибку типа.

Ответ 2

Я также нашел ответ здесь: http://markthomas.info/blog/?p=92

Типы типов

Заказ может быть смешано с любым классом; он не зависит от каких-либо методов или полей класса, в которые он смешивается. Иногда полезно для того, чтобы черта могла использовать поля или методы класса, к которому она смешана, это можно сделать, указав для типа типа тип. Тип типа может быть указан для класса или признака следующим образом:

trait SpellChecker { self =>
  ...
}

self в контексте этого признака будет ссылаться на это. Слияние это полезно для вложенных классов или черт, где в противном случае было бы трудно получить доступ к определенному этому. Синтаксис может быть расширен, чтобы указать нижние границы на этом, когда это будет сделано, этот признак или класс могут использовать функции этого низкоуровневого класса, поэтому он может расширять или изменять его поведение.

trait SpellChecker { self: RandomAccessSeq[char] =>
  ...
}

Компилятор проверяет, что любой класс в иерархии, включая SpellChecker, или расширяет RandomAccessSeq [ char], поэтому SpellChecker теперь может использовать поля или методы RandomAccessSeq [char]

Ответ 3

Чтобы ответить на другую половину вашего вопроса (почему println(s.self) создает ошибку?), это потому, что self не является полем SelfAware. Его можно использовать для определения таких полей:

trait SelfAware { self =>
  val me = self
}

class X
val x = new X with SelfAware
println(s.me)