Advertisement
Guest User

Untitled

a guest
Jul 27th, 2016
74
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.93 KB | None | 0 0
  1. trait U {
  2. self =>
  3. val name = "outer"
  4. val b = new AnyRef {
  5. val name = "inner"
  6. println(name)
  7. println(this.name)
  8. println(self.name)
  9. }
  10. }
  11.  
  12. // Another example:
  13. trait Foo{
  14. this: { def close:Unit} =>
  15. ...
  16. }
  17. // Here the self type here is a structural type.
  18. // The effect is to say that anything that mixes in Foo must implement a no-arg "close" method returning unit.
  19. // This allows for safe mixins for duck-typing.
  20.  
  21. // 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:
  22. // provide an alternative way of associating a class with an abstract type:
  23.  
  24. abstract class Graph {
  25. type Node <: BaseNode; // The abstract Node type is upper-bounded by BaseNode to express that we want nodes to support a connnectWith method
  26. class BaseNode {
  27. self: Node =>
  28. def connectWith(n: Node): Edge =
  29. // This method creates a new instnce of class Edge which links the receiver node with the argument node.
  30. 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.
  31. def self: Node; // Thus, we have to state somehow that the identity of class BaseNode has to be expressible as type Node.
  32.  
  33. // Node is called the selftype of class BaseNode. When a selftype is given, it is taken as the type of this inside the class.
  34. // Without a selftype annotation, the type of this is taken as usual to the type of the class itself
  35. }
  36. class Edge(from: Node, to: Node) {
  37. def source() = from;
  38. def target() = to;
  39. }
  40. }
  41.  
  42. class LabeledGraph extends Graph {
  43. class Node(label: String) extends BaseNode {
  44. def getLabel: String = label;
  45. // Concreate subclasses of Graph have to define a concrete Node class for which it is
  46. // possible to implement method self
  47. def self: Node = this;
  48. }
  49. }
  50.  
  51. // This programming pattern appears quite frequently when family polymorphism is combined with explict reference to this.
  52. // Therefore, Scala supports a mechanism for specifying the type of this explicitly.
  53.  
  54. // The selftype of a class must be a subtype of the selftypes of all its base classes.
  55. // 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.
  56.  
  57. // Here is another example to demostrate the difference between a self type and extending a trait.
  58. // If you say B extends A, then B is an A.
  59. // However, when you do dependency injection, you want B to require A, not to be an A.
  60.  
  61. // For example:
  62.  
  63. trait User { def name:String }
  64.  
  65. trait Tweeter {
  66. user: User =>
  67. def tweet(msg:String) = println(s"$name: $msg")
  68.  
  69. trait Wrong extends Tweeter {
  70. // Error: illegal inheritance.
  71. // self-type Wrong does not conform to Tweeter's selftype Tweeter with User
  72. def noCanDo = name // error: not found: value name
  73. }
  74. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement