我試圖創建一個庫,可以將距離從一個單位轉換爲另一個。理想情況下,我可以在一個單元中指定距離,當傳遞給需要不同單元的方法時,scala編譯器會自動將其轉換。這是我到目前爲止有:斯卡拉隱式轉換類型參數
abstract class BaseUnit(scale: Option[Double] = None) {
def unit: String
def scalingFactor: Double = scale match {
case Some(factor) => factor
case None => 1.0
}
}
object Cm {
implicit def inch2cm(inch: Inch):Cm = new Cm(Some(0.393 * inch.scalingFactor))
}
class Cm(scale: Option[Double] = None) extends BaseUnit(scale) {
def unit: String = "cm"
}
object Inch {
implicit def cm2inch(cm: Cm):Inch = new Inch(Some(2.54 * cm.scalingFactor))
}
class Inch(scale: Option[Double] = None) extends BaseUnit(scale) {
def unit: String = "inch"
}
class Distance[A <: BaseUnit](val scalar: Double, val unit: A) {
override def toString: String = (scalar*unit.scalingFactor)+unit.unit
}
def foo(x: Distance[Cm], y: Distance[Cm]): String = x.toString()+","+y.toString()
使用它,而無需顯式聲明的類型參數似乎讓斯卡拉使用Nothing
類型:
val a = new Distance(10, new Inch)
println(foo(a, a))
> scala test.scala
found : this.Distance[Nothing]
required: this.Distance[this.Cm]
Note: Nothing <: this.Cm, but class Distance is invariant in type A.
You may wish to define A as +A instead. (SLS 4.5)
println(foo(a, a))
^
one error found
繼編譯器的建議,導致富返回10.0inch,10.0inch
,而不是預計3.93cm,3.93cm
。
如果我明確地指定了類型,編譯器就會找出差異,但仍不會將一個隱式轉換爲另一個。
val a = new Distance[Inch](10, new Inch)
println(foo(a, a))
// found : this.Distance[this.Inch]
// required: this.Distance[this.Cm]
// println(foo(a, a))
// ^
// one error found
我做錯了什麼,還是編譯器不允許這種使用隱式轉換?
首先:爲什麼'Distance'類具有類型參數'A'開頭?你似乎沒有在任何地方使用它...... – ghik
@ghik哎呀,我在我的實際代碼中使用A,並且在構建這個例子時一定會意外地將它拿出來。現在修復它 – Matt