user1078671
user1078671

Reputation:

Why do i need explicitly use self-type in the given example?

While reading and trying to get all the concepts behind scalable components in Scala from this, i still can't fully understand why this example should have self type:

abstract class Graph {
  type Node <: NodeLike
    trait NodeLike {    // without self: Node => won't compile
      def connectWith(n: Node) =
    new Edge(this, n)
    }           
    class Edge(from: Node, to: Node)
}

abstract type Node is a subtype of NodeLike and this is an object of type NodeLike which suites according to the given upper constraint. Any detailed explanation would be appreciated.

Upvotes: 0

Views: 91

Answers (2)

Jatin
Jatin

Reputation: 31724

Well it rightly fails because of the bound Node <: NodeLike. When you are doing new Edge(this,n), you are simply passing argument types as NodeLike, Node to Edge. But your Edge expects 'Node,Node`:

class Edge(from: Node, to: Node)

i.e. you are trying to pass NodeLike to Node (NodeLike is super type of Node). Thats like passing an Animal to a function that is expecting Dog (The issue, is if it is allowed then you could pass any Animal including cat to one expecting Dog)

A work around would be :

abstract class Graph {
    type Node <: NodeLike
    trait NodeLike { // without self: Node => won't compile
      def connectWith(n: Node) =
        new Edge(this, n)
    }
    class Edge(from: NodeLike, to: Node)
  }

Or another way would be as you have mentioned where you explicitly guarantee that the argument you are passing is of type Node and not NodeLike.

Upvotes: 3

Lee
Lee

Reputation: 144126

In the definition

def connectWith(n: Node) = new Edge(this, n)

this has type NodeLike, however the constructor for Edge requires that from is of type Node, which is a subtype of NodeLike. You need the self type annotation to ensure that this has the required type of Node.

Upvotes: 0

Related Questions