2010-05-18 71 views
7

更具體地說BigInt如何工作將int轉換爲BigInt?有人可以解釋我在Scala中的隱式轉換嗎?

在源代碼中有這麼一句話:

... 
implicit def int2bigInt(i: Int): BigInt = apply(i) 
... 

這是怎麼代碼中調用?

我能理解這個其他樣本是如何工作的:"Date literals"

In。

val christmas = 24 Dec 2010 

定義是:

implicit def dateLiterals(date: Int) = new { 
    import java.util.Date 
    def Dec(year: Int) = new Date(year, 11, date) 
} 

int獲取的與int作爲參數傳遞的消息Dec,系統將查找可以處理請求的另一種方法,在這種情況下Dec(year:Int)

Q1。我對日期文字的理解是否正確? Q2302。它如何適用於BigInt?

由於

+0

我認爲您指的是隱式轉換。隱式參數稍有不同。 – GClaramunt 2010-05-18 22:53:12

+0

[Scala編程第1版](http://www.artima.com/pins1ed/):[隱式轉換和參數](http://www.artima.com/pins1ed/implicit-conversions-and-parameters。 html) – user272735 2012-06-29 09:20:18

回答

11

當所提供的類型不匹配的預期類型,Scala編譯器會在範圍內的任何方法標記隱式,是以提供的類型作爲參數並返回預期的類型作爲結果。如果找到,它會在兩者之間插入對該方法的調用。 在BigInt有情況下,假設你有一個方法

doSomethingWithBigInt(d:BigInt)=.... 

你用一個整數稱之爲:

doSomethingWithBigInt(10) 

由於類型不匹配,Scala編譯器將生成:

doSomethingWithBigInt(int2bigInt(10)) 

假設隱式int2bigInt在範圍內

+2

爲了澄清,它使用了一個隱含的*,如果它使得代碼不會以其他方式編譯,否則不僅僅是如果有一個隱式接受找到的類型作爲它的參數。 – 2010-05-18 23:03:26

+3

範圍thingy是一個紅色的鯡魚。如果已經推斷出目標類,Scala將在原始類的伴隨對象中以及目標類的伴隨對象中搜索此類含義。在這種情況下,由於目的類是明確的BigInt,所以BigInt的對象夥伴將被搜索隱含。 – 2010-05-18 23:51:22

+0

我不想詳細說明範圍:) – GClaramunt 2010-05-19 00:53:47

7

隱含的點當只有一個正確的方法去做時,凝灰岩將填補無聊的樣板材料。

對於隱式參數的情況,編譯器從上下文插入一個參數,該參數必須是您所想的。例如,

case class TaxRate(rate: BigDecimal) { } 
implicit var sales_tax = TaxRate(0.075) 
def withTax(price: BigDecimal)(implicit tax: TaxRate) = price*(tax.rate+1) 

scala> withTax(15.00) 
res0: scala.math.BigDecimal = 16.1250 

由於我們已經標出稅率作爲一個隱含參數,並提供了可以在需要時填寫的隱含變量,我們並不需要指定稅率。編譯器在withTax(15.00)(sales_tax)

自動填充的隱式轉換的情況下,編譯器會尋找能接受它有一個類型,並將其轉換爲所需要的類型的方法。此轉換在正常情況下無法鏈接,因此您必須在一步步驟中獲得所需的內容。

有兩種情況可能會發生隱式轉換。一個是在參數的一個方法調用 - 如果類型是錯誤的,但它可以轉換爲正確的類型(正好以一種方式),那麼編譯器會爲你轉換。另一種是在存在的方法調用 - 如果實際使用的類型沒有可用的方法,但可以將其轉換爲具有該方法的類型,那麼轉換將發生,然後方法將被調用。

讓我們看看每個例子。

implicit def float2taxrate(f: Float) = TaxRate(BigDecimal(f)) 
scala> withTax(15.00)(0.15f) 
res1: scala.math.BigDecimal = 17.250000089406967200 

在這裏,我們稱明確的稅率爲0.15f。這與參數不匹配,該參數必須是TaxRate,但編譯器發現我們可以使用隱含的float2taxrate將花車變成稅率。所以它對我們來說,呼叫withTax(15.00)(float2taxrate(0.15f))

現在的另一個例子。

class Currency(bd: BigDecimal) { 
    def rounded = bd.setScale(2,BigDecimal.RoundingMode.HALF_EVEN) 
} 
implicit def bigdec2currency(bd: BigDecimal) = new Currency(bd) 
scala> withTax(15.00)(0.15f).rounded 
res66: scala.math.BigDecimal = 17.25 

的BigDecimal沒有rounded方法,所以withTax(15.00)(0.15f)不應該是能夠調用一個(因爲它返回一個BigDecimal)。但是我們定義了一個Currency,它有一個rounded方法,並且轉換爲Currency,因此隱式轉換會填充所有詳細信息:bigdec2currency(withTax(15.00)(0.15f)).rounded

在從IntBigInt的轉換的情況下,編譯器將在例如嘗試添加7 + BigInt(5)時使用它。這不會正常工作 - 7是一個IntInt不知道如何將自己添加到BigInt。但BigInt有一個方法+可以將自己添加到另一個BigInt。編譯器看到,如果只有它可以將7轉換爲BigInt,它可以使用該方法。隱式轉換允許進行轉換,因此它將7 + BigInt(5)轉換爲int2bigInt(7)+BigInt(5)

(注:int2bigInt在裏面BigInt定義,所以使用它,你必須import BigInt._它反過來又推遲到BigInt對象的apply(i: Int)方法,這是什麼讓你寫BigInt(5)和它的工作(而不是。必須通過與Java中的BigInteger一樣的字符串)。)

+0

謝謝!這比我的解釋更詳細。 – GClaramunt 2010-05-19 13:55:14

+0

您可能已經足夠了,但我決定爲那些不熟悉Scala的人留下更長的參考資料/教程。 – 2010-05-19 14:40:54