Scala มีข้อจำกัดในการแปลงอัตโนมัติในการเพิ่มวิธีการ กล่าวคือ จะไม่ใช้การแปลงมากกว่าหนึ่งรายการในการพยายามค้นหาวิธีการ ตัวอย่างเช่น:
class A(val n: Int)
class B(val m: Int, val n: Int)
class C(val m: Int, val n: Int, val o: Int) {
def total = m + n + o
}
// This demonstrates implicit conversion chaining restrictions
object T1 { // to make it easy to test on REPL
implicit def toA(n: Int): A = new A(n)
implicit def aToB(a: A): B = new B(a.n, a.n)
implicit def bToC(b: B): C = new C(b.m, b.n, b.m + b.n)
// won't work
println(5.total)
println(new A(5).total)
// works
println(new B(5, 5).total)
println(new C(5, 5, 10).total)
}
แก้ไข: ขอบเขตการดู ('‹%') เลิกใช้แล้วตั้งแต่ Scala 2.11 https://issues.scala-lang.org/browse/SI-7629 (คุณสามารถใช้คลาสประเภทแทนได้)
อย่างไรก็ตาม หากคำจำกัดความโดยนัยต้องใช้พารามิเตอร์โดยนัยเอง (ขอบเขตของมุมมอง) Scala จะ ค้นหาค่าโดยนัยเพิ่มเติมตราบเท่าที่จำเป็น ต่อจากตัวอย่างสุดท้าย:
// def m[A <% B](m: A) is the same thing as
// def m[A](m: A)(implicit ev: A => B)
object T2 {
implicit def toA(n: Int): A = new A(n)
implicit def aToB[A1 <% A](a: A1): B = new B(a.n, a.n)
implicit def bToC[B1 <% B](b: B1): C = new C(b.m, b.n, b.m + b.n)
// works
println(5.total)
println(new A(5).total)
println(new B(5, 5).total)
println(new C(5, 5, 10).total)
}
"เวทมนตร์!" คุณอาจพูดว่า ไม่เป็นเช่นนั้น นี่คือวิธีที่คอมไพเลอร์จะแปลแต่ละรายการ:
object T1Translated {
implicit def toA(n: Int): A = new A(n)
implicit def aToB(a: A): B = new B(a.n, a.n)
implicit def bToC(b: B): C = new C(b.m, b.n, b.m + b.n)
// Scala won't do this
println(bToC(aToB(toA(5))).total)
println(bToC(aToB(new A(5))).total)
// Just this
println(bToC(new B(5, 5)).total)
// No implicits required
println(new C(5, 5, 10).total)
}
object T2Translated {
implicit def toA(n: Int): A = new A(n)
implicit def aToB[A1 <% A](a: A1): B = new B(a.n, a.n)
implicit def bToC[B1 <% B](b: B1): C = new C(b.m, b.n, b.m + b.n)
// Scala does this
println(bToC(5)(x => aToB(x)(y => toA(y))).total)
println(bToC(new A(5))(x => aToB(x)(identity)).total)
println(bToC(new B(5, 5))(identity).total)
// no implicits required
println(new C(5, 5, 10).total)
}
ดังนั้น ในขณะที่ bToC
ถูกใช้เป็นการแปลงโดยนัย aToB
และ toA
จะถูกส่งเป็นพารามิเตอร์โดยนัย แทนที่จะถูกโยงกันเป็นการแปลงโดยนัย
แก้ไข
คำถามที่เกี่ยวข้องที่น่าสนใจ:
person
Daniel C. Sobral
schedule
16.03.2011