我正在嘗試 Scala 上的示例程式implicits。我正在嘗試實施“不耐煩的 Scala ”一書中的一種解決方案。
我已經撰寫了 Fraction 類,它具有兩個成員變數numerator和denominator以及操作多載方法“* (fraction) ”,這樣我們就可以在 Fraction 物件上呼叫乘法,例如fration1 * fraction2 * fraction3。
現在,我嘗試實作intToFraction和fractionToInt隱式方法,這樣我們也可以撰寫像 2 fraction1 3 這樣的語法。我嘗試在 Fraction 類的伴生物件中實作這些方法。但是這些方法沒有被呼叫。
正如 Scala 檔案所建議的那樣,Scala 編譯器將嘗試找出伴隨物件中的隱式實作。在這里,我們正在對 Fraction 類的物件執行操作,所以我假設 Fraction 中宣告的隱式應該被自動呼叫。我也嘗試過顯式匯入隱式方法,但它不起作用。
請在下面找到代碼片段以供參考。
package com.example.implicits.conversion
object ImplicitConversionTester extends App {
val f1 = Fraction(4,2)
val result = 2 * f1
println(s"${f1 * f1}")
println(s"${result}")
}
class Fraction(val numerator : Int,val denominator : Int) {
def *(fraction : Fraction): Fraction = {
println("##### Call to operator overloading *")
Fraction(this.numerator*fraction.numerator, this.denominator*fraction.denominator)
}
override def toString: String = s"Fraction($numerator,$denominator) ===== ${numerator/denominator}"
}
object Fraction {
def apply(numerator: Int, denominator: Int): Fraction = new Fraction(numerator, denominator)
implicit def intToFraction(num : Int) = {
println("##### intToFraction")
Fraction(num,1)
}
implicit def fractionToInt(fr : Fraction) = {
println("##### fractionToInt")
fr.numerator/fr.denominator
}
}
任何解決此問題的建議表示贊賞!
uj5u.com熱心網友回復:
你是對的,scala編譯器首先尋找隱式
- 那么當前范圍
- 然后在同伴范圍內
- 在匯入范圍內
在你的情況下,編譯器在主單例物件的范圍內尋找隱式,ImplicitConversionTester它不會找到任何東西,因為沒有任何可用的隱式。如果您匯入隱式,那么它應該可以作業 -
object Implicit extends App {
import Fraction._
class Fraction(val numerator : Int,val denominator : Int) {
def * (fraction : Fraction): Fraction = {
println("##### Call to operator overloading *")
Fraction(this.numerator*fraction.numerator, this.denominator*fraction.denominator)
}
}
object Fraction {
def apply(numerator: Int, denominator: Int): Fraction = new Fraction(numerator, denominator)
implicit def intToFraction(num : Int) = {
println("##### intToFraction")
Fraction(num,1)
}
implicit def fractionToInt(fr : Fraction) = {
println("##### fractionToInt")
fr.numerator/fr.denominator
}
}
println(Fraction(1,2) * 2)
}
uj5u.com熱心網友回復:
問題在于沒有明確提及回傳型別的隱式方法的宣告。我沒有在上面的代碼片段中提到回傳型別。添加函式回傳型別后,隱式作業正常。因此,無需顯式匯入ImplicitConversionTester類中的隱式函式來解決問題。
以下是修復錯誤的更新分數類:
class Fraction(val numerator : Int,val denominator : Int) {
val test = 2
def *(fraction : Fraction): Fraction = {
println("##### Call to operator overloading *")
Fraction(this.numerator*fraction.numerator, this.denominator*fraction.denominator)
}
override def toString: String = s"Fraction($numerator,$denominator) ===== ${numerator/denominator}"
}
object Fraction {
def apply(numerator: Int, denominator: Int): Fraction = new Fraction(numerator, denominator)
implicit def intToFraction(num : Int) : Fraction = { // RETURN TYPE FRACTION
println("##### intToFraction")
Fraction(num,1)
}
implicit def fractionToInt(fr : Fraction) : Int = { // ADDED RETURN TYPE INT
println("##### fractionToInt")
fr.numerator/fr.denominator
}
}
下面分享有關 Scala 編譯器如何查找隱式轉換的更多詳細資訊。下圖取自《不耐煩的 Scala》一書。

如書中所述,Scala 編譯器優先考慮源型別或目標型別的伴生物件。
Here, What is source and target type that depends on the order of expression. For example, if the expression is "2*Fraction(2,4)", the expression is evaluated from left to right. Int "2" has already implementation present for multiplication method (*). So, compiler tries to find implicit conversion from "Fraction to Int" in "Int" type first. As "Int" type does not have any implementation for "Fraction to Int", compiler will lookup companion object of Fraction class where it finds a method "fractionToInt". In this example, target type is Int and Source type is Fraction.
Consider the example of expression "Fraction(2,4)*2", Here as the Fraction class has implementation available for multiplication "*", compiler tries to find implicit for converting Int to Fraction. So target type is Fraction and Source type is Int. As there is no such implicit method/class present in Int class, compiler looksup Fraction companion object and finds "IntToFraction" implicit.
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/444247.html
上一篇:在Scala2中合并2個元組
