简体   繁体   中英

How to represent contravariant type parameter using bounds

Here is original trait that can be implemented easily without any problems:

trait ZPar[-KNV,+KV] {
  def get(i: KNV):List[KV]
}

Now I'm trying to emulate variances using bounds (similar to what dotty is doing)

trait ZPar[KNV,KV] {
   def get[R  >: KNV](i: R):List[_<:KV]
}

Looks good so far. Until I'm trying to implement it:

object ZParImp extends ZPar[String,Int]{
  override def get(i: String):List[_<:Int] = {
    val v:String = i
    List(5)
  }
}
//ERROR: method get overrides nothing

Method get cannot be overriden like that.

Is there any way to override method get ?

If we provide a type parameter, imitating the original, it seems to work.

object ZParImp extends ZPar[String,Int]{
  override def get[S >: String](i: S):List[_<:Int] = {
    val v :S = "blah"  // <--it's a String
    List(5)
  }
}

I don't think you can do precisely what you want. All you know about R >: String is that String is an R , not that your R is a String . If R was Any you wouldn't expect to be able to do what you want to do.

In the contravariant example, R is fixed by the instance rather than the method. So this approach achieves the same thing:

trait ZPar[KNV, KV] {
  type R >: KNV
  def get(i: R): List[_ <: KV]
}

object ZParImp extends ZPar[String,Int] {

  type R = String

  override def get(i: R): List[_ <: Int] = {
    val v: String = i
    List(5)
  }

}

But obviously that approach has its drawbacks, and may not be what you were trying to achieve.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM