簡體   English   中英

Scala 類型 arguments 不符合類型參數界限

[英]Scala type arguments do not conform to type parameter bounds

我正在做一些我想概括的工作(一些行為在幾個類中完全重復,但針對不同的具體類型 [稱為 C,見下文]),為了能夠使用所有具體類型之間共有的那些接口的一些行為(聽起來非常抽象和籠統......解釋我的問題的最佳方法是查看代碼)。

我用類似的結構簡化了真實的代碼,只是為了演示這個問題

package playground

object Conformance {
  trait S
  trait G
  trait R {
    type ST <: S
    type GT <: G

    def getS: ST
    def getG: GT
  }
  trait RT[SD <: S, GD <: G] extends R {
    override type ST = SD
    override type GT = GD
  }
  
  final case class ConcreteS() extends S

  final case class ConcreteG() extends G

  final class C1 extends RT[ConcreteS, ConcreteG] {
    override def getS: ConcreteS = ConcreteS()

    override def getG: ConcreteG = ConcreteG()
  }
  //some different impl
  final class C2 extends RT[ConcreteS, ConcreteG]{
    override def getS: ConcreteS = ConcreteS()

    override def getG: ConcreteG = ConcreteG()
  }
  //some different impl
  final class C3 extends RT[ConcreteS, ConcreteG]{
    override def getS: ConcreteS = ConcreteS()

    override def getG: ConcreteG = ConcreteG()
  }

  //generic impl over W
  trait GeneralizationOverW[C <: RT[S, G]] {
   // With `<: RT[S, G]` restriction I know C is RT with some S and G I can use S and G behaviours
  }
  
  class W1 extends GeneralizationOverW[C1]
  class W2 extends GeneralizationOverW[C2]
  class W3 extends GeneralizationOverW[C3]

}


想象一下, C1,C2,C3有不同的實現(由代碼生成),我嘗試使用不同的 C 和GeneralizationOverW來概括 W

我試圖閱讀 Scala 規范中的復合類型,但無法弄清楚為什么會出現以下編譯錯誤以及如何修復它:

類型 arguments [playground.Conformance.C1] 不符合特征 GeneralizationOverW 的類型參數界限 [C <: playground.Conformance.RT[playground.Conformance.S,playground.Conformance.G]] class W1 擴展 GeneralizationOverW[C1]

編輯:建議后更新代碼:

package playground

object Conformance {
  trait S
  trait SS extends S
  trait G
  trait R {
    type ST <: S
    type GT <: G

    def getS: ST
    def getG: GT
  }
  trait RT[SD <: S, GD <: G] extends R {
    override type ST = SD
    override type GT = GD
  }

  final case class ConcreteS1() extends SS
  final case class ConcreteS2() extends SS
  final case class ConcreteS3() extends SS

  final case class ConcreteG1() extends G
  final case class ConcreteG2() extends G
  final case class ConcreteG3() extends G

  final class C1 extends RT[ConcreteS1, ConcreteG1] {
    override def getS: ConcreteS1 = ConcreteS1()

    override def getG: ConcreteG1 = ConcreteG1()
  }
  //some different impl
  final class C2 extends RT[ConcreteS2, ConcreteG2]{
    override def getS: ConcreteS2 = ConcreteS2()

    override def getG: ConcreteG2 = ConcreteG2()
  }
  //some different impl
  final class C3 extends RT[ConcreteS3, ConcreteG3]{
    override def getS: ConcreteS3 = ConcreteS3()

    override def getG: ConcreteG3 = ConcreteG3()
  }

  //generic impl over W
  trait GeneralizationOverW[ST <: S,GT <: G , CON <: RT[ST, GT]] {
    //  With `<: RT[S, G]` restriction I know C is RT with some S and G I can use S and G behaviours
  }

  class W1 extends GeneralizationOverW[ConcreteS1,ConcreteG1,C1]
  class W2 extends GeneralizationOverW[ConcreteS2,ConcreteG2,C2]
  class W3 extends GeneralizationOverW[ConcreteS3,ConcreteG3,C3]


}

我認為它現在有效:)

我不確定這是您正在尋找的,但您可以嘗試:

trait GeneralizationOverW[S1 <: S, G1 <: G, C <: RT[S1, G1]] {
  // With `<: RT[S, G]` restriction I know C is RT with some S and G I can use S and G behaviours
}

class W1 extends GeneralizationOverW[ConcreteS, ConcreteG, C1]
class W2 extends GeneralizationOverW[ConcreteS, ConcreteG, C2]
class W3 extends GeneralizationOverW[ConcreteS, ConcreteG, C3]

有幾件事正在發生:

trait GeneralizationOverW[C <: RT[S, G]] {

}

它預計此處傳遞的C將准確擴展RT[S, G] ,使用SG而不是它的子類型,因為RT在兩個參數中都是不變的。

您可以通過添加+使其成為協變的

trait RT[+SD <: S, +GD <: G] {
  def getS: SD
  def getG: GD
}

我刪除了extends R因為路徑相關的類型STGT在這里定義:

trait R {
  type ST <: S
  type GT <: G

  def getS: ST
  def getG: GT
}

是不變的,不能成為協變的。 如果您放棄使用R (您的示例根本沒有使用路徑相關類型),您可以創建一個有效代碼:

object Conformance {
  trait S
  trait G

  trait RT[+SD <: S, +GD <: G] {
    def getS: SD
    def getG: GD
  }

  final case class ConcreteS() extends S

  final case class ConcreteG() extends G

  final class C1 extends RT[ConcreteS, ConcreteG] {
    override def getS: ConcreteS = ConcreteS()

    override def getG: ConcreteG = ConcreteG()
  }
  //some different impl
  final class C2 extends RT[ConcreteS, ConcreteG]{
    override def getS: ConcreteS = ConcreteS()

    override def getG: ConcreteG = ConcreteG()
  }
  //some different impl
  final class C3 extends RT[ConcreteS, ConcreteG]{
    override def getS: ConcreteS = ConcreteS()

    override def getG: ConcreteG = ConcreteG()
  }

  //generic impl over W
  trait GeneralizationOverW[C <: RT[S, G]] {
   // With `<: RT[S, G]` restriction I know C is RT with some S and G I can use S and G behaviours
  }

  class W1 extends GeneralizationOverW[C1]
  class W2 extends GeneralizationOverW[C2]
  class W3 extends GeneralizationOverW[C3]

}

但是,如果您確實需要這些依賴於路徑的類型,則應將硬編碼的SG替換為 @TomerShetah 答案中的綁定參數。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM