【问题标题】:How to represent contravariant type parameter using bounds如何使用边界表示逆变类型参数
【发布时间】:2019-03-16 04:47:54
【问题描述】:

这是可以轻松实现而没有任何问题的原始特征:

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

现在我正在尝试使用边界来模拟方差(类似于 dotty 所做的)

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

目前看起来不错。直到我尝试实现它:

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

方法get 不能像那样被覆盖。

有没有办法覆盖方法get

【问题讨论】:

    标签: scala generics types


    【解决方案1】:

    我认为你不能完全按照自己的意愿行事。你只知道R &gt;: StringStringR,而不是你的RString。如果RAny,你就不会期望能够做你想做的事。

    在逆变示例中,R 由实例而非方法固定。所以这种方法达到了同样的效果:

    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)
      }
    
    }
    

    但显然这种方法有其缺点,可能不是您想要达到的目标。

    【讨论】:

      【解决方案2】:

      如果我们提供一个类型参数,模仿原来的,它似乎可以工作。

      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)
        }
      }
      

      【讨论】:

      • 这里的问题是我不能使用 val i 作为方法体内的字符串。协方差不存在这样的问题。即使我们确切地知道iString,这一行:val v:String = i 也不会编译。所以val v :S 不是String 而是字符串上方的东西。
      • 你是对的。 i 很容易成为 String-able 但不是真正的 String。嗯。
      猜你喜欢
      • 2014-04-30
      • 2011-12-14
      • 1970-01-01
      • 2014-12-01
      • 2012-04-07
      • 1970-01-01
      • 2022-12-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多