implicit的用法

本文深入解析Scala中的Implicit概念,包括隐式参数、隐式类型转换及隐式调用函数的使用方法,并通过具体示例帮助理解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

掌握implicit的用法是阅读spark源码的基础,也是学习scala其它的开源框架的关键,implicit 可分为:

  • 隐式参数
  • 隐式转换类型
  • 隐式调用函数

1.隐式参数

当我们在定义方法时,可以把最后一个参数列表标记为implicit,表示该组参数是隐式参数。一个方法只会有一个隐式参数列表,置于方法的最后一个参数列表。如果方法有多个隐式参数,只需一个implicit修饰即可。 当调用包含隐式参数的方法是,如果当前上下文中有合适的隐式值,则编译器会自动为改组参数填充合适的值。如果没有编译器会抛出异常。当然,标记为隐式参数的我们也可以手动为该参数添加默认值。def foo(n: Int)(implicit t1: String, t2: Double = 3.14)

scala > def calcTax(amount: Float)(implicit rate: Float): Float = amount * rate
scala > implicit val currentTaxRate = 0.08F
scala > val tax = calcTax(50000F) // 4000.0
  • 1
  • 2
  • 3

如果编译器在上下文没有找到第二行代码会报错

2.隐式地转换类型

使用隐含转换将变量转换成预期的类型是编译器最先使用 implicit 的地方。这个规则非常简单,当编译器看到类型X而却需要类型Y,它就在当前作用域查找是否定义了从类型X到类型Y的隐式定义 
例子:

scala> val i: Int = 3.5 //直接报错
加上这句:
scala> implicit def double2Int(d: Double) = d.toInt
再运行,没报错
scala> val i: Int = 3.5  //i=3
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

3.隐式调用函数

隐式调用函数可以转换调用方法的对象,比如但编译器看到X .method,而类型 X 没有定义 method(包括基类)方法,那么编译器就查找作用域内定义的从 X 到其它对象的类型转换,比如 Y,而类型Y定义了 method 方法,编译器就首先使用隐含类型转换把 X 转换成 Y,然后调用 Y 的 method。 
例子:

class SwingType{
  def  wantLearned(sw : String) = println("兔子已经学会了"+sw)
}
object swimming{
  implicit def learningType(s : AminalType) = new SwingType
}
class AminalType
object AminalType extends  App{
  import com.mobin.scala.Scalaimplicit.swimming._
  val rabbit = new AminalType
    rabbit.wantLearned("breaststroke")         //蛙泳
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

上例中编译器在rabbit对象调用时发现对象上并没有wantLearning方法,此时编译器就会在作用域范围内查找能使其编译通过的隐式视图,找到learningType方法后,编译器通过隐式转换将对象转换成具有这个方法的对象,之后调用wantLearning方法

### C# 关键字分类 对于给定的关键字列表,在C#中这些关键字可以根据其性质分为两类:保留字和上下文关键字。 #### 保留字(Reserved Keywords) 保留字是在任何情况下都具有特殊意义的单词,不能作为标识符使用。以下是属于保留字的部分关键字: - `int`[^1] - `class` - `float` - `double` - `char` - `string` - `bool` - `void` #### 上下文关键字(Contextual Keywords) 上下文关键字只有在特定语境中有特殊含义,而在其他地方可以用作标识符。这里列举了一些可能被认为是上下文关键字的例子: - `public` - `private` - `protected` - `static` - `new` - `if` - `else` - `switch` 请注意上述分类基于提供的关键字列表,并且部分关键字如`if`, `else`, 和 `switch`通常也被视为保留字而非仅限于上下文关键字。 ### IMPLICIT 关键字解析 关于`implicit`关键字的应用主要体现在几种不同的编程语言环境中,下面分别介绍不同语言里该关键字的作用。 #### C++ 在C++中,`explicit`用于防止编译器执行某些隐式的类型转换操作,而`implicit`并不是一个合法的关键字;相反,当不声明为`explicit`时,默认允许这种隐含转换发生。这意味着如果构造函数未被标记为`explicit`,那么它可以参与自动类型转换过程[^2]。 #### Scala 相比之下,在Scala中`implicit`是一个有效并广泛使用的特性。它主要用于两个方面——隐式转换与隐式参数。前者是指通过定义带有一个参数的方法来进行类型的自动转换;后者则是指那些可以在调用时不显式传递但在运行期间由编译器自动查找并应用的参数[^3]。 ```scala // 定义一个隐式转换函数 implicit def intToString(x: Int): String = "" + x // 使用隐式参数 def greet(implicit name: String) = println(s"Hello, $name") val greetingMessage = "World" greet // 编译器会寻找名为"greetingMessage"的隐式值并将其作为参数传入 ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值