scala implicit关键字用法总结

转自:
scala implicit 关键字用法总结
Scala implicit 使用简介

implicit关键字是scala中一个比较有特点的关键字,他保证了scala在很多时候没有一些不必要的代码冗余,使得scala看起来更加整洁,同时使得scala的一些库在设计的时候,可以有更加直观的操作方法。

隐式参数

隐式参数(implicit parameters)是最简单的形态,也是最容易理解的。与函数中增加默认值的效果类似,但是更为灵活。

object ImplicitParameters{
  implicit val name: String = "default"  // name名称可与下面参数名称不同,他是根据变量类型进行推导替换的
  log("init")
  
def log(msg:String)(implicit name:String): Unit = { println(s"[$name] $msg ")}

def process(): Unit = {
  implicit val name = "process"
  log("doing something")  
}

def main(args: Array[String]): Unit = {
  implicit val name = "main"
  log("start")
  process()
  log("end")("custom name")
}
}

// 输出如下
[default] init
[main] start
[process] doing something
[custom name] end

在运行时,函数的隐式参数会自动去寻找符合条件类型的隐式变量,然后进行变量替换。需要注意的是,想同类型的隐式变量只能定义一个,不然会报错,编译器解析的时候不知道该替换哪一个。

隐式参数有三种定义方法:

  • def func(implicit x: Int), x是implicit的;
  • def func(x: Int)(implicit y:Int), y是implicit的;
  • def func(implicit x:Int, y:Int), x, y都是implicit的;

以下定义方式是错误的,无法通过:

def err(x: Int, implicit y:Int)
def err(implicit x:Int)(implicit y:Int)
def err(implicit x:Int)(y:Int)

隐式函数

隐式函数用于类型转换。如当函数输入类型与实际要求类型不符合时,编译器会自动搜寻可用的隐式函数对数据进行类型转换,使得程序正常运行。相当于给了一个修复编译器调用错误的机会,同时也赋予了强大的扩展能力,可以更为方便地实现 DSL。

import scala.language.implicitConversions
//这个import是为了避免出现warning
object Test extends App {
  implicit def conv(a: Int) = {
    println("in conv")
    a.toString
  }
  def say(b: String) = println(b)
  say(5)
}
//输出结果:
// in conv
// 5
//这说明过程是say(conv(5))
//原因是编译器在检查的时候发现需要一个String类型的参数,但是代入的是一个Int,于是
//他会在范围内寻找implicit的function,找到了符合这个要求的String => Int的function,然后调用

隐式类

implicit class MyClass(x: Int)

隐式类是隐式函数的一个语法糖(一个不恰当的比喻是Python的装饰器函数和装饰器类)。其作用主要是类的主构造函数可以作为隐式转换的参数,相当于其主构造函数可以用来当做一个implicit的function,如下例:

object Test{
  implicit class MyName(x:Int){
    println("I'm in cons")
    val y = x
  }
  
  def say(x:MyName) = {
    println(x.y)
  }
say(5)
}

# 输出结果
I'm in cons
5

这里的MyName是一个隐式类,其主构造函数可以用作隐式转换,所以say需要一个MyName类型的参数,但是调用的时候给的是一个Int,这里就会调用MyName的主构造函数转换为一个MyName的对象,然后在println其y的值。

隐式转换规则

1、标记规则:隐式转换中涉及到的变量、函数、类都是带有implicit关键词的,也就是说隐式转换必须有implicit定义才能生效;

2、作用域规则:在隐式转换使用的位置必须是单标识符可见的,也就是可以无前缀引用,例如,可以是x,但不可以是foo.x;

3、作用域规则延伸:作用域规则未找到的情况下,会在类型的隐式作用域(伴生对象)内查找,吟诗作用域是指与该类型相关联的全部伴生模块;

4、代码优先规则:隐式转换触发的时机是在编译器出现了查找方法失败的情况下才会被触发,因此如果代码可以正常执行的话,是不会触发隐式转换的;

5、有且只有一次隐式转换规则:触发一次隐式转换,只能转换一次。如x+y的x触发隐式转换,只会被隐式转换为convert(x)+y,而不会进行两次隐式转换convert2(convert1(x))+y。

需注意的点:
1、在使用的时候,不要再一个作用域内不要定义多个相同类型的隐式变量,因为隐式变量是根据类型匹配,所以定义多个相同类型的隐式变量,会报编译错误,编译器无法进行选择。另外,隐式变量本身也是可以在作用域内使用和变量一样的遮蔽(shadow)。实践中,建议新建特定的只包含一个变量的类,来保证可以明确地进行预期的隐式转换,不会被其他不经意的代码 shadow;

2、在使用隐式函数的时候,请 import scala.language.implicitConversions,否则编译的时候会有一个警告:warning: there was one feature warning; re-run with -feature for details。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,651评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,468评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,931评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,218评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,234评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,198评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,084评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,926评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,341评论 1 311
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,563评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,731评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,430评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,036评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,676评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,829评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,743评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,629评论 2 354