Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- trait U {
- self =>
- val name = "outer"
- val b = new AnyRef {
- val name = "inner"
- println(name)
- println(this.name)
- println(self.name)
- }
- }
- // Another example:
- trait Foo{
- this: { def close:Unit} =>
- ...
- }
- // Here the self type here is a structural type.
- // The effect is to say that anything that mixes in Foo must implement a no-arg "close" method returning unit.
- // This allows for safe mixins for duck-typing.
- // Section 2.3 "Selftype Annotations" of Martin Odersky's original Scala paper Scalable Component Abstractions explains the purpose of selftype beyond mixin composition very well:
- // provide an alternative way of associating a class with an abstract type:
- abstract class Graph {
- type Node <: BaseNode; // The abstract Node type is upper-bounded by BaseNode to express that we want nodes to support a connnectWith method
- class BaseNode {
- self: Node =>
- def connectWith(n: Node): Edge =
- // This method creates a new instnce of class Edge which links the receiver node with the argument node.
- new Edge(self, n); // illegal!! Because the type of the self reference this is BaseNode and therefore does not conform to type Node which is expected by the constructor of class Edge.
- def self: Node; // Thus, we have to state somehow that the identity of class BaseNode has to be expressible as type Node.
- // Node is called the selftype of class BaseNode. When a selftype is given, it is taken as the type of this inside the class.
- // Without a selftype annotation, the type of this is taken as usual to the type of the class itself
- }
- class Edge(from: Node, to: Node) {
- def source() = from;
- def target() = to;
- }
- }
- class LabeledGraph extends Graph {
- class Node(label: String) extends BaseNode {
- def getLabel: String = label;
- // Concreate subclasses of Graph have to define a concrete Node class for which it is
- // possible to implement method self
- def self: Node = this;
- }
- }
- // This programming pattern appears quite frequently when family polymorphism is combined with explict reference to this.
- // Therefore, Scala supports a mechanism for specifying the type of this explicitly.
- // The selftype of a class must be a subtype of the selftypes of all its base classes.
- // When instantiating a class in a new expression, it is checked that the selftype of the class is a supertype of the type of the object being created.
- // Here is another example to demostrate the difference between a self type and extending a trait.
- // If you say B extends A, then B is an A.
- // However, when you do dependency injection, you want B to require A, not to be an A.
- // For example:
- trait User { def name:String }
- trait Tweeter {
- user: User =>
- def tweet(msg:String) = println(s"$name: $msg")
- trait Wrong extends Tweeter {
- // Error: illegal inheritance.
- // self-type Wrong does not conform to Tweeter's selftype Tweeter with User
- def noCanDo = name // error: not found: value name
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement