barii
barii

Reputation: 345

variances and bounds together

What I need is, let say, I have a List trait, and Value trait, and special lists store special Value types. I tried this, but line.value doesn't exist, and the reason is, it looks like prepend's type parameter is not the actual SingleValue class, but it is still a template. But why? thanks

sealed trait Value
case class SingleValue(value: Int) extends Value
case class DoubleValue(value1: Int, value2: Int) extends Value


trait List1  {
  def prepend[B <: Value](value: B): Int
}

case class SingleList1 extends List1 {

  def prepend[SingleValue](line: SingleValue): Int = {
    line.value
  }
}

Upvotes: 0

Views: 55

Answers (1)

Dima
Dima

Reputation: 40500

SingleValue in def prepend[SingleValue](line: SingleValue) is a type parameter, not a concrete type.

Like when you wrote def prepend[B <: Value](value: B): Int, you used B as a variable def prepend[SingleValue] has exactly the same meaning (except that variable name is different, but that's immaterial).

It is not very clear from your question what exactly you are trying to do here ... but, if I am guessing correctly, you want to parametrize the class, not the method:

   trait List1[B <: Value] {
      def prepend(b: B): Int
   }

   class SingleList extends List1[SingleValue] { 
      def prepend(sv: SingleValue) = sv.value
   }

Update So, if you want your List1 to be covariant, as you mentioned in the comment, that won't work: if it did, then SingleList would be a subclass of List1[Value], and therefore prepend would have to work with any Value, not just SingleValue, and it doesn't know how.

What you could do in that case, is define the specialized prepend method "on the side" and associate it with List1 via an implicit conversion:

trait Lis1[+B <: Value]
    
object List1Ops { 
  implicit class SVL[T <: SingleValue](val l: List1[T]) extends AnyVal {
     def prepend(v: T) = v.value
  }
}

This let's you do both things like:

val svl = new List1[SingleValue]{}
println(svl.prepend(new SingleValue))

and

val l: List1[Value] = new List1[SingleValue]{} // still covariant

Is that what you are after?

Upvotes: 2

Related Questions