Search code examples
scalapolymorphismsubtype

Scala Inheritance of Type Constructor


Right now, I am trying to implement a variant of a Linked List with the following code, but I am having trouble with it. Basically, I am trying to create different type of nodes that will connect with each other by the next method. Thus, I have two classes, NodeA[T] and NodeB[T], that inherited from the abstract class, NodeTrait[T]. I just want next to be any type that is a subtype of NodeTrait[T] and is contained in Option. Thus, I want next to be either the type Option[NodeA[T]] or Option[NodeB[T]].

However, I get a compiler error saying expression of type Option[NodeTrait[T]] doesn't confirm to expected type NodeTrait[T]. I am not exactly sure how to solve this problem. I was thinking about using covariance and change NodeTrait[T] to NodeTrait[+T] but I still get more compiling errors. Does anybody have any tips to solve this issue?

abstract class NodeTrait[T](x:T) {
  var next:Option[NodeTrait[T]]
  def insert(y: T):Option[NodeTrait[T]]
}



class NodeA[T](x:T) extends  NodeTrait[T](x){
  def insert(y: T): NodeTrait[T] = {
    val newnode = new NodeA[T](y)
    next = Some(new NodeA[T](y))
    next
  }
  next = None

}

class NodeB[T](x:T) extends  NodeTrait[T](x){
  def insert(y: T): NodeTrait[T] = {
    val newnode = new NodeB[T](y)
    next = Some(new NodeB[T](y))
    next
  }
  next = None



}

Solution

  • I don't know what your code do, lets assume it's just simplified abstract version of something, but here edited code that compiles:

    abstract class NodeTrait[T](x:T) {
      var next:Option[NodeTrait[T]]
      def insert(y: T):Option[NodeTrait[T]]
    }
    
    
    class NodeA[T](x:T) extends  NodeTrait[T](x){
      def insert(y: T): Option[NodeTrait[T]] = {
        val newnode = new NodeA[T](y)
        next = Some(new NodeA[T](y))
        next
      }
      var next: Option[NodeTrait[T]] = None
    
    }
    
    class NodeB[T](x:T) extends  NodeTrait[T](x){
      def insert(y: T): Option[NodeTrait[T]] = {
        val newnode = new NodeB[T](y)
        next = Some(new NodeB[T](y))
        next
      }
    
     var next: Option[NodeTrait[T]] = None
    }
    

    You specified different (from NodeTrait) return types in you NodeB and NodeA insert method.