为什么我会收到 "type arguments...do not conform to trait..." 编译器错误?
Why am I getting an error of "type arguments...do not conform to trait..." compiler error?
我已经被 IntelliJ (14.1.5) 中的 Scala (2.11.7) 编译器错误卡住了好几个小时了。我在 Google 上搜索过,绞尽脑汁尝试了很多变体,但似乎无法绕过它。
我已经获取了代码上下文并将其剪裁得尽可能小(包括剪裁掉任何外部库依赖项)以捕获我一直用来尝试缩小问题范围的域。我以为我使用的是非常简单的惯用 Scala; case 对象、带有类型参数的 traits 等
最后一行以 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 中的 "Build All"),将发出两个错误:
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]] {
我可能刚刚在这方面工作的时间太长了,现在眼睛有黄疸。一个多小时以来,我还没有想到任何新的方法来解决这个问题。所以,任何关于我做错了什么的指导将不胜感激。
嗯,根据 Coordinate
的限制,您需要 LongitudeRadian <: Longitude[CoordinateRadian.unitBase.type]
(纬度也类似),这是错误的,因为 LatitudeRadian.basesAsTuple._1.type
不是 [=15= 的子类型](编译器只知道 LatitudeRadian.basesAsTuple._1
是一个 Angle.UnitBase.Member
)。如果你只是从 basesAsTuple
和 unitBase
中删除类型注释,编译器 will infer the singleton types without problems.
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.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.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.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.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
}
}
但老实说,这对我来说似乎过度使用了单例类型。我根本不明白您为什么需要 unitBase
和 basesAsTuple
。我更愿意写
abstract case class LongitudeRadian(theta: Double) extends Longitude[RADIAN.type]
abstract case class CoordinateRadian private[CoordinateRadian] (longitude: LongitudeRadian, latitude: LatitudeRadian) extends Coordinate[RADIAN.type, LongitudeRadian, LatitudeRadian]
等被无法证明两个对象相同的编译器咬住的机会要少得多。
我已经被 IntelliJ (14.1.5) 中的 Scala (2.11.7) 编译器错误卡住了好几个小时了。我在 Google 上搜索过,绞尽脑汁尝试了很多变体,但似乎无法绕过它。
我已经获取了代码上下文并将其剪裁得尽可能小(包括剪裁掉任何外部库依赖项)以捕获我一直用来尝试缩小问题范围的域。我以为我使用的是非常简单的惯用 Scala; case 对象、带有类型参数的 traits 等
最后一行以 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 中的 "Build All"),将发出两个错误:
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]] {
我可能刚刚在这方面工作的时间太长了,现在眼睛有黄疸。一个多小时以来,我还没有想到任何新的方法来解决这个问题。所以,任何关于我做错了什么的指导将不胜感激。
嗯,根据 Coordinate
的限制,您需要 LongitudeRadian <: Longitude[CoordinateRadian.unitBase.type]
(纬度也类似),这是错误的,因为 LatitudeRadian.basesAsTuple._1.type
不是 [=15= 的子类型](编译器只知道 LatitudeRadian.basesAsTuple._1
是一个 Angle.UnitBase.Member
)。如果你只是从 basesAsTuple
和 unitBase
中删除类型注释,编译器 will infer the singleton types without problems.
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.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.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.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.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
}
}
但老实说,这对我来说似乎过度使用了单例类型。我根本不明白您为什么需要 unitBase
和 basesAsTuple
。我更愿意写
abstract case class LongitudeRadian(theta: Double) extends Longitude[RADIAN.type]
abstract case class CoordinateRadian private[CoordinateRadian] (longitude: LongitudeRadian, latitude: LatitudeRadian) extends Coordinate[RADIAN.type, LongitudeRadian, LatitudeRadian]
等被无法证明两个对象相同的编译器咬住的机会要少得多。