我一直卡在IntelliJ(14.1.5)的Scala(2.11.7)編譯器錯誤現在幾個小時。我已經谷歌搜索,扼殺了我的大腦,並嘗試了大量的變化,但似乎無法繞過它。爲什麼我會收到「類型參數...不符合特性......」編譯器錯誤的錯誤?
我已經採取了代碼上下文,並儘可能小地剪裁它(包括刪除任何外部庫依賴項)以捕獲我一直用來嘗試縮小問題的域。我以爲我使用的是非常直接的慣用Scala;情況下的物體,與類型參數性狀等
從開始abstract case class CoordinateRadian
最後一行的第四個是一個產生這個Scala編譯錯誤:
Error:(128, 129) type arguments [Test.this.CoordinateRadian.unitBase.type,Test.this.LongitudeRadian,Test.this.LatitudeRadian] do not conform to trait Coordinate's type parameter bounds [U <: Test.this.Angle.UnitBase.Member,+O <: Test.this.Longitude[U],+A <: Test.this.Latitude[U]] abstract case class CoordinateRadian private[CoordinateRadian] (longitude: LongitudeRadian, latitude: LatitudeRadian) extends Coordinate[CoordinateRadian.unitBase.type, LongitudeRadian, LatitudeRadian] {
下面是與編譯器錯誤的代碼:
package org.public_domain
class Test {
object Angle {
object UnitBase {
trait Member
case object RADIAN extends Member
case object DEGREE extends Member
}
trait UnitBase[U <: Angle.UnitBase.Member] {
def unitBase: U
}
object ZeroBase {
trait Member
case object LEFT extends Member
case object MIDDLE extends Member
}
trait ZeroBase[U <: Angle.UnitBase.Member, Z <: Angle.ZeroBase.Member] extends Angle.UnitBase[U] {
def zeroBase: Z
}
}
trait Angle[U <: Angle.UnitBase.Member, Z <: Angle.ZeroBase.Member] extends Angle.ZeroBase[U, Z] {
def theta: Double
}
trait Angle__ObjectBase {
def basesAsTuple: (Angle.UnitBase.Member, Angle.ZeroBase.Member)
}
object AngleRadianMiddle extends ((Double) => AngleRadianMiddle) with Angle__ObjectBase {
val basesAsTuple: (Angle.UnitBase.Member, Angle.ZeroBase.Member) =
(Angle.UnitBase.RADIAN, Angle.ZeroBase.MIDDLE)
def apply(theta: Double): AngleRadianMiddle =
new AngleRadianMiddle(theta) {
def unitBase =
basesAsTuple._1
def zeroBase =
basesAsTuple._2
private def readResolve(): Object =
AngleRadianMiddle(theta)
def copy(thetaNew: Double = theta): AngleRadianMiddle =
AngleRadianMiddle(thetaNew)
}
}
abstract case class AngleRadianMiddle private[AngleRadianMiddle] (theta: Double) extends Angle[AngleRadianMiddle.basesAsTuple._1.type, AngleRadianMiddle.basesAsTuple._2.type] {
def copy(thetaNew: Double = theta): AngleRadianMiddle
}
trait Itude[U <: Angle.UnitBase.Member] extends Angle[U, Angle.ZeroBase.MIDDLE.type] {
val zeroBase =
Angle.ZeroBase.MIDDLE
}
sealed trait Longitude[U <: Angle.UnitBase.Member] extends Itude[U]
sealed trait Latitude[U <: Angle.UnitBase.Member] extends Itude[U]
object LongitudeRadian extends ((Double) => LongitudeRadian) {
val basesAsTuple: (Angle.UnitBase.Member, Angle.ZeroBase.Member) =
(Angle.UnitBase.RADIAN, Angle.ZeroBase.MIDDLE)
def apply(theta: Double): LongitudeRadian =
new LongitudeRadian(theta) {
def unitBase =
basesAsTuple._1
private def readResolve(): Object =
LongitudeRadian(theta)
def copy(thetaNew: Double = theta): LongitudeRadian =
LongitudeRadian(thetaNew)
}
}
abstract case class LongitudeRadian(theta: Double) extends Longitude[LongitudeRadian.basesAsTuple._1.type] {
def copy(thetaNew: Double = theta): LongitudeRadian
}
object LatitudeRadian extends ((Double) => LatitudeRadian) {
val basesAsTuple: (Angle.UnitBase.Member, Angle.ZeroBase.Member) =
(Angle.UnitBase.RADIAN, Angle.ZeroBase.MIDDLE)
def apply(theta: Double): LatitudeRadian =
new LatitudeRadian(theta) {
def unitBase =
basesAsTuple._1
private def readResolve(): Object =
LatitudeRadian(theta)
def copy(thetaNew: Double = theta): LatitudeRadian =
LatitudeRadian(thetaNew)
}
}
abstract case class LatitudeRadian(theta: Double) extends Latitude[LatitudeRadian.basesAsTuple._1.type] {
def copy(thetaNew: Double = theta): LatitudeRadian
}
trait Coordinate[U <: Angle.UnitBase.Member, +O <: Longitude[U], +A <: Latitude[U]] {
def longitude: O
def latitude: A
val x: O =
longitude
val y: A =
latitude
}
object CoordinateRadian extends ((LongitudeRadian, LatitudeRadian) => CoordinateRadian) {
val unitBase: Angle.UnitBase.Member =
Angle.UnitBase.RADIAN
def apply(longitude: LongitudeRadian, latitude: LatitudeRadian): CoordinateRadian =
new CoordinateRadian(longitude, latitude) {
private def readResolve(): Object =
CoordinateRadian(longitude, latitude)
def copy(longitudeNew: LongitudeRadian = longitude, latitudeNew: LatitudeRadian = latitude): CoordinateRadian =
CoordinateRadian(longitudeNew, latitudeNew)
}
}
//abstract case class CoordinateRadian private[CoordinateRadian] (longitude: LongitudeRadian, latitude: LatitudeRadian) extends Coordinate[CoordinateRadian.unitBase.type, Longitude[CoordinateRadian.unitBase.type], Latitude[CoordinateRadian.unitBase.type]] {
abstract case class CoordinateRadian private[CoordinateRadian] (longitude: LongitudeRadian, latitude: LatitudeRadian) extends Coordinate[CoordinateRadian.unitBase.type, LongitudeRadian, LatitudeRadian] {
def copy(longitudeNew: LongitudeRadian = longitude, latitudeNew: LatitudeRadian = latitude): CoordinateRadian
}
}
您會注意到文件末尾的第五行是一個註釋掉的行(與文件末尾的第四行非常相似)。如果從端線取消對第五,然後註釋掉從端線的第四和編譯代碼(「全部構建」中的IntelliJ),兩個錯誤會發出:
Error:(125, 67) overriding method longitude in trait Coordinate of type => Test.this.Longitude[Test.this.CoordinateRadian.unitBase.type]; value longitude has incompatible type abstract case class CoordinateRadian private[CoordinateRadian] (longitude: LongitudeRadian, latitude: LatitudeRadian) extends Coordinate[CoordinateRadian.unitBase.type, Longitude[CoordinateRadian.unitBase.type], Latitude[CoordinateRadian.unitBase.type]] {
Error:(125, 95) overriding method latitude in trait Coordinate of type => Test.this.Latitude[Test.this.CoordinateRadian.unitBase.type]; value latitude has incompatible type abstract case class CoordinateRadian private[CoordinateRadian] (longitude: LongitudeRadian, latitude: LatitudeRadian) extends Coordinate[CoordinateRadian.unitBase.type, Longitude[CoordinateRadian.unitBase.type], Latitude[CoordinateRadian.unitBase.type]] {
我可能只是工作在這太久了,現在有一個黃疸的眼睛。我還沒有想到在一個多小時內有任何新的方法來解決這個問題。所以,對於我做錯什麼的指導將不勝感激。
太棒了! Tysvm!我非常感謝你的回答。當然,它會引發下一個問題......爲什麼我在這些聲明中重複完全相同的類型信息(如果標識是身份...)會導致編譯器變得困惑?我遇到了很多編譯器問題的另一個方向(錯誤地推斷類型),我贊成在默認情況下指定類型。現在即使過度指定(以身份爲基礎)也會導致編譯器問題,這是相當令人沮喪的。 – chaotic3quilibrium
你是如何在冥府中找到答案的?是什麼讓你認爲去基地AsTuple和unitBase的類型超標?我只是試圖通過我將來如何爲自己做同樣的事情。你是否有一些額外的工具,你正在使用的表面更多的是什麼編譯器正在做什麼,它是困惑,導致你這些特定的聲明?這不是我曾經考慮過的路線(根據我的身份假設)。 – chaotic3quilibrium
正如我所說的,只要查看「座標」的約束條件和「CoordinateRadian」和「LatitudeRadian」的類型參數就可以清楚地說明問題。您不是「重複相同的信息」:編譯器推斷例如'val basesAsTuple:(Angle.UnitBase.RADIAN.type,Angle.ZeroBase.MIDDLE。類型)'在'LatitudeRadian'中,_not_'val basesAsTuple:(Angle.UnitBase.Member,Angle.ZeroBase.Member)'。所以它知道'LatitudeRadian.basesAsTuple._1'是'Angle.UnitBase.RADIAN'和'LatitudeRadian.basesAsTuple._1.type'與'Angle.UnitBase.RADIAN.type'是相同的,這就是約束所要求的。 –