在遠離 Scala 幾年后,我一直在重新學習它。我現在試圖理解隱含和隱含的解決方案(這在過去對我來說一直是個問題)。我遇到了一些事情,表明我可能有比我想象的更根本的誤解——尤其是在范圍界定和匯入方面。
考慮以下:
class A {
def test(using n: Int): String = n.toString
}
object A {
given n: Int = 2
}
object Main extends App {
println((new A()).test)
}
如果我嘗試編譯它,我會收到以下錯誤:
沒有為類 A 中方法測驗的引數 n 找到 Int 型別的隱式引數
我不明白為什么會這樣。如果我將列印運算式更改為以下內容:
println((new A()).test(using A.n))
它有效(我花了很長時間才發現這實際上是一種允許的語法)。
顯然,另一個解決方案是執行以下操作:
import A.given
println((new A()).test)
這也有效。
從這個答案中,隱含在一個型別的伴隨物件中搜索(這里就是這種情況)。所以,我的問題是,我想,為什么編譯器允許我直接參考A.n,但它不能自己找到隱含的值?為什么需要進口?它看起來很像它在范圍內,應該得到解決。
我的部分困惑來自檔案:
import子句用于訪問其他包中的成員(類、特征、函式等)。訪問同一包的成員不需要匯入子句。
(來自檔案)。正如object A“同一個包的一部分”一樣,為什么我需要匯入它或它的任何成員?而且,一般來說,當類或物件在范圍內且可見時,何時需要匯入成員?這在 Scala3 中是否發生了變化?
編輯
只是在玩,我還嘗試了以下方法:
class A {
def test(using n: Int): String = n.toString
}
object A {
given n: Int = 2
}
given n: Int = 5
object Main extends App {
import A.given
println((new A()).test)
}
我希望得到一個關于模棱兩可的隱式決議的編譯器錯誤,但它作業并列印了2. 我不明白為什么這會奏效。如果我注釋掉它列印的匯入5,至少與我在上面看到的一致。
uj5u.com熱心網友回復:
沒有為類 A 中方法測驗的引數 n 找到 Int 型別的隱式引數
這是預期的,在這種情況下沒有implicit/given Int在范圍內。
PS:我想你已經知道了,這只是一個練習,但Int永遠不應該這樣implicit
我不明白為什么會這樣。如果我將列印運算式更改為以下內容:
println((new A()).test(using A.n))
那么它可以作業
好吧,在那種情況下,您正在顯式傳遞引數,不再有隱式決議。
你甚至可以做類似的事情
println((new A()).test(using 3))
是一樣的,那里沒有什么特別的事情發生。
顯然,另一個解決方案是執行以下操作:
import A.given
在這種情況下,您會將 中的所有given值添加object A到當前范圍。
當然,這解決了最初的問題,因為現在有一個given Int范圍和隱式解決方案按預期作業。
從這個答案中,隱含在一個型別的伴隨物件中搜索(這里就是這種情況)。
實際上并非如此。
這里的型別是Int,并且伴隨object的Int沒有定義任何given值。
所以,我的問題是,我想,為什么編譯器允許我直接參考 An 但它不能自己找到隱含值?
它允許您參考它,因為編譯器將始終允許您使用相對或完整路徑參考任何值(只要意味著可見性約束)。這與您撰寫任何代碼時所做的相同,這里沒有與隱式相關的內容。
而且,編譯器再次找不到它,因為這樣的值不在隱式范圍內,所以編譯器不會尋找它。
(來自檔案)。由于物件 A 是“同一個包的一部分”,為什么我需要匯入它或它的任何成員?
你不需要匯入它來訪問它的成員,就像你之前展示的那樣,你可以很容易地訪問它A.n
我希望得到一個關于模棱兩可的隱式決議的編譯器錯誤,但它作業并列印了 2。我不明白為什么會這樣。如果我注釋掉匯入,它會列印 5,這至少與我在上面看到的一致。
這個其實很棘手,但是隱式決議有一個權重的概念。規范說,如果在范圍內找到兩個隱式值,則將選擇最具體的一個。只有當兩者具有相同的權重時,才會引發模棱兩可的錯誤。
在進口的情況下,它們總是有更多的重量。并進一步匯入“影子”以前的(順便說一句,常規值也會發生這種情況)。
還有建議,如果你用一個真實的例子可能會更容易理解;不像Int
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/496928.html
下一篇:ClassCastException:org.apache.spark.sql.catalyst.expressions.GenericRowWithSchema不能被強制轉換
