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