隐含的东西的重点是在显然只有一种正确的方法时填充无聊的样板文件。
在隐式参数的情况下,编译器从上下文中插入一个参数,该参数必须是您所想的。例如,
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
。这与必须为 type 的参数不匹配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)
不应该调用一个方法(因为它返回 a BigDecimal
)。但是我们已经定义了一个Currency
确实有一个rounded
方法和一个到 的转换Currency
,所以隐式转换填充了所有的细节:bigdec2currency(withTax(15.00)(0.15f)).rounded
.
在从Int
to转换的情况下BigInt
,编译器将在例如尝试添加 时使用它7 + BigInt(5)
。这不会正常工作 -7
是一个Int
并且Int
不知道如何将自己添加到BigInt
. 但是BigInt
有一种方法+
可以将自己添加到另一个BigInt
. 并且编译器看到,只要它可以转换7
为 a BigInt
,它就可以使用该方法。隐式转换允许该转换,因此它转换7 + BigInt(5)
为int2bigInt(7)+BigInt(5)
.
(注意:int2bigInt
是在内部定义的BigInt
,所以要使用它,你必须使用它import BigInt._
。它又遵循对象的apply(i: Int)
方法BigInt
,这让你可以编写BigInt(5)
并让它工作(而不是像BigInteger
在 Java 中那样传递一个字符串) .)