[英]Scala implicit conversion of type parameters
我正在嘗試創建一個可以將一個單位的距離轉換為另一個單位的庫。 理想情況下,我能夠以一個單位指定距離,當傳遞給需要不同單位的方法時,讓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()
在沒有顯式說明type參數的情況下使用它似乎使Scala使用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
遵循編譯器的建議,結果foo返回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
我是在做錯什么,還是編譯器不允許使用這種隱式轉換?
你只需要
class Distance[A <: BaseUnit](val scalar: Double, val unit: A) { ... }
因此,編譯器有理由不使A
過於具體。 否則,可以選擇Nothing
因為它與您所做的任何事情都不相關。
另外,您知道如何在單位之間進行轉換,但是還沒有教過如何在距離之間進行轉換。 您可以:
implicit def convertDist[A <: BaseUnit, B <: BaseUnit](da: Distance[A])(implicit a2b: (A => B)): Distance[B] = new Distance[B](da.scalar, a2b(da.unit))
或類似的東西。 (正如您現在所定義的,順便說一下,轉換是向后的。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.