Evans Y.
Evans Y.

Reputation: 4419

How to use scala trait with `self` reference?

I saw some code write trait as following:

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

I'd like to know why the error happened and how to use trait in this way?

Upvotes: 29

Views: 18051

Answers (3)

Evans Y.
Evans Y.

Reputation: 4419

I also found the answer here: http://markthomas.info/blog/?p=92

Self Types

Ordered can be mixed in to any class; it doesn’t depend on any methods or fields of the class that it is mixed in to. Sometimes it’s useful for a trait to be able to use the fields or methods of a class it is mixed in to, this can be done by specifying a self type for the trait. A self type can be specified for a class or a trait as follows:

trait SpellChecker { self =>
  ...
}

self within the context of this trait will refer to this. Aliasing this is useful for nested classes or traits where it would otherwise be difficult to access a particular this. The syntax can be extended to specify a lower-bounds on this, when this is done the trait or class can use the features of this lower-bound class, so it can extend or modify its behaviour.

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

The compiler will check that any class in a hierarchy including SpellChecker is or extends RandomAccessSeq[char], so SpellChecker can now use the fields or methods of RandomAccessSeq[char]

Upvotes: 21

Dan Burton
Dan Burton

Reputation: 53675

To answer the other half of your question (why does println(s.self) produce an error?), that is because self is not a field of SelfAware. It can be used to define such fields, however:

trait SelfAware { self =>
  val me = self
}

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

Upvotes: 12

Apocalisp
Apocalisp

Reputation: 35054

The error is occurring because you have constrained the type of the this reference (which you have named self) to be of type Self. When you say new Self with SelfAware, this is OK, because that object is of type Self like you asked. But when you say new X with SelfAware, there is no evidence that X is in any way a subtype of Self.

In your new object of type X with SelfAware, what would be the type of its self member? Well, it would not be of type Self, but of type X. But you have defined the trait SelfAware so that self must be of type Self, so you get a type error.

Upvotes: 22

Related Questions