一. Implicit关键字

  1. 隐士转换

    (1)隐士转换函数:用implicit修饰的,只有一个参数的函数。他会被自动执行,来把一个值转换成另一个

    1. class RichFile(val f:File){
    2. def read = Source.fromFile(f).mkString
    3. }
    4. implicit def file2richFile(f:File) = new RichFile(f) //隐士转换函数
    5. val result: String = new File("/home/lj/chrome.sh").read
    6. println(result)

(2)隐士转换函数可以卸载伴生对象中,需要的时候import进来

(3)当一个隐士函数没有被scala调用,可以显示的调用函数,有可能出现错误提示

【注】:

  1. (a) 隐士转换优先转换参数,后去尝试转换调用方法的对象
  2. (b) 隐士转换不能同时使用多个转换。eg:convert1(convert2(a))
  3. (c) 二义性错误:如果2个隐士转换函数都能用到参数转换,则编译器报错
  1. 函数的隐士参数

    (1)函数参数列表中的某个参数,用implicit生命,则这个函数成为包含隐士参数的函数。

    (2)调用隐士参数的函数,可以显式传入参数,也可以省略不传,scala从上下文查找隐士对象,自动传进函数中

    1. class Delimeters(val left:String,val right:String){}
    2. def quote(value:String)(implicit delimeters: Delimeters)=println(delimeters.left+value+delimeters.right)
    3. quote("spark")(new Delimeters("<",">")) //显示调用
    4. implicit val deli = new Delimeters("<<",">>")
    5. quote("hadoop") // 自动推断
  2. 隐士转换function作为函数的隐士参数

    有时一个函数的参数类型为泛型T,不能确定参数有哪些方法可被调用。因此,函数的参数类表中,使用隐士转换函数作为参数,从而确定参数列表有哪些方法能被调用

    1. //Predef中含有大量的T->Ordered[T]的隐士转换函数
    2. def getBigger[T](a:T,b:T)(implicit ord : T=>Ordered[T])={ //ord是一个隐士转换函数,用implicit修饰后,成为隐士参数。scala要根据前文查找是否有这样一个函数
    3. if(a>b) a else b
    4. }
    5. println(getBigger(2,3))
  3. 上下文界定

    上下文界定是对隐士参数的简化语法,这个隐士参数的类型要是M[T],简化掉函数参数中的隐士参数。那函数内部如何使用原来的隐士参数呢,2种方法:定义内部函数,把省略的隐士参数在内部函数中还原出来;第二个是用implicity还原这个变量

    1. object Test extends App{
    2. // 隐士参数
    3. def max[T](a:T,b:T)(implicit cp:Ordering[T])={
    4. if (cp.compare(a,b)>0) a else b
    5. }
    6. println(max(1,3))
    7. // 上下文界定精简隐士参数,表示的语义还是要有Ordering[T]类型的隐士参数
    8. def max2[T:Ordering](a:T,b:T)={
    9. // 1.内部函数使用隐士参数
    10. def innermax(implicit op:Ordering[T]) = {
    11. if (op.compare(a,b)>0) a else b
    12. }
    13. innermax
    14. }
    15. println(max2(3,6))
    16. // 2. implicify还原隐士参数
    17. def max3[T:Ordering](a:T,b:T)={
    18. val op = implicitly[Ordering[T]]
    19. if (op.compare(a,b)>0) a else b
    20. }
    21. println(max3(23,1))
    22. }
  4. 类型证明参数

    (1)格式:implicit 类型证明参数名:泛型1 <:<,<%<,<=< 泛型2

    (2)作用:当函数右两个泛型时,类型证明参数可以证明一个泛型是另一个泛型的(子类型,视图类型,相等类型)

    1. //firstlast方法,会在调用时确定2个类型。C:函数的参数类型。A是iterable里的类型(List中的元素类型)。
    2. def firstLast[A,C](it:C)(implicit demonstrate: C<:<Iterable[A]) = { // 如果没有类型证明参数demonstrate,定义函数时,无法确定C是什么类型。也就无法调用参数的方法
    3. (it.head,it.last)
    4. }
    5. println(firstLast(List(1,2,5))) // scala推断出泛型[Int,List[Int]]
    6. println(firstLast[Int,List[Int]](List(1,2,5))) // 手动指定泛型[Int,List[Int]]

二. @implicitNotFound注解

  1. @implicitNotFound

    @implicitNotFound注解在无法找到隐士参数,隐士转换,或推出的泛型不匹配时给出提示信息

    1. @implicitNotFound(msg = "Cannot prove that ${From} <:< ${To}.")
    2. sealed abstract class <:<[-From, +To] extends (From => To) with Serializable
  2. Manifest和typetag

  1. // Manifest和typetag存储被擦出泛型信息
  2. class Foo{class Bar}
  3. def m(f: Foo)(b: f.Bar)(implicit ev: TypeTag[f.Bar]) = ev // TypeTag解决Manifest的依赖路径问题
  4. val f1 = new Foo;val b1 = new f1.Bar
  5. val f2 = new Foo;val b2 = new f2.Bar
  6. val ev1 = m(f1)(b1)
  7. val ev2 = m(f2)(b2)
  8. println(ev1==ev2) // false。 使用manifest的结果是true

scala高级内容(二) - Implicit的更多相关文章

  1. scala高级内容(一) Case Class

    一. 操作符 自定义操作符 操作付默认左结合调用.除了以:结尾的操作符是右结合调用 object OperaterTest extends App{ val a: myInt = new myInt( ...

  2. Scala进阶之路-Scala高级语法之隐式(implicit)详解

    Scala进阶之路-Scala高级语法之隐式(implicit)详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 我们调用别人的框架,发现少了一些方法,需要添加,但是让别人为你一 ...

  3. 一个完整的Installshield安装程序实例—艾泽拉斯之海洋女神出品(四) --高级设置二

    原文:一个完整的Installshield安装程序实例-艾泽拉斯之海洋女神出品(四) --高级设置二 上一篇:一个完整的安装程序实例—艾泽拉斯之海洋女神出品(三) --高级设置一4. 根据用户选择的组 ...

  4. Lucene的查询及高级内容

    Lucene查询 基本查询: @Test public void baseQuery() throws Exception { //1. 创建查询的核心对象 FSDirectory d = FSDir ...

  5. ASP.NET MVC深入浅出(被替换) 第一节: 结合EF的本地缓存属性来介绍【EF增删改操作】的几种形式 第三节: EF调用普通SQL语句的两类封装(ExecuteSqlCommand和SqlQuery ) 第四节: EF调用存储过程的通用写法和DBFirst模式子类调用的特有写法 第六节: EF高级属性(二) 之延迟加载、立即加载、显示加载(含导航属性) 第十节: EF的三种追踪

    ASP.NET MVC深入浅出(被替换)   一. 谈情怀-ASP.NET体系 从事.Net开发以来,最先接触的Web开发框架是Asp.Net WebForm,该框架高度封装,为了隐藏Http的无状态 ...

  6. 02.Scala高级特性:第6节 高阶函数;第7节 隐式转换和隐式参数

    Scala高级特性 1.    课程目标 1.1.   目标一:深入理解高阶函数 1.2.   目标二:深入理解隐式转换 2.    高阶函数 2.1.   概念 Scala混合了面向对象和函数式的特 ...

  7. Stm32高级定时器(二)

    Stm32高级定时器(二) 1 主从模式:主?从? 谈论主从,可知至少有两个以上的触发或者驱动信号,stm32内部有多个定时器,可以相互之间驱动或者控制. 主模式:定时器使能只受驱动时钟控制或者输出控 ...

  8. Solidity高级理论(二):Gas

    solidity高级理论(二):Gas 关键字:Gas.结构体.节省小技巧 Gas是什么 在Solidity中,用户想要执行DApp都需要支付一定量的Gas,Gas可以用以太币购买,所以,用户每次使用 ...

  9. Scala学习(二)——高级特性

    apply() 方法 apply方法是Scala提供的一个语法糖 类名+括号,调用对象的apply方法 对象名+括号,调用类的apply方法 对apply方法的简单测试:(其中,带 new -- cl ...

随机推荐

  1. 《Java程序设计》第二次实验报告

    20145220 <Java程序设计>第二次实验报告 课程:Java程序设计 指导教师:娄嘉鹏 实验日期:2016.04.12 实验名称:Java面向对象程序设计 实验内容 初步掌握单元测 ...

  2. nginx和apache下的url rewrite

    将服务器上面的数据同步到本地之后,发现打开首页显示不正常,本地服务器是apache,经过打开url rewrite之后本地首页正常显示. 原因是phpwind本身支持了url rewrite的功能,但 ...

  3. Linux 命令ln

    在linux中可用ln命令创建一个文件的链接(软链接或者硬链接) 硬链接的使用: root@IdeaPad:~# ln 2.txt e.txt root@IdeaPad:~# ls 1.txt 2.t ...

  4. ExtJS4.2.1自定义主题(theme)样式详解

    (基于Ext JS 4.2.1版本) UI组件 学习ExtJS就是学习组件的使用.ExtJS4对框架进行了重构,其中最重要的就是形成了一个结构及层次分明的组件体系,由这些组件形成了Ext的控件. Ex ...

  5. MySQL-python模块

    1.  Python 操作 Mysql 模块的安装 linux: pip install MySQL-python 或 yum -y install MySQL-python windows: exe ...

  6. android:id="@+id/button1" 与 android:id="@id/button1" 区别 @string

    一.android:id="@+id/button1" 与 android:id="@id/button1" 区别 android:id="@+id/ ...

  7. PHP-通过strace定位故障原因

    俗话说:不怕贼偷,就怕贼惦记着.在面对故障的时候,我也有类似的感觉:不怕出故障,就怕你不知道故障的原因,故障却隔三差五的找上门来. 十一长假还没结束,服务器却频现高负载,Nginx出现错误日志: co ...

  8. error LNK2026: 模块对于 SAFESEH 映像是不安全的

    解决方法: 1.打开该项目的“属性页”对话框. 2.单击“链接器”文件夹. 3.单击“命令行”属性页. 4.将 /SAFESEH:NO 键入“附加选项”框中,然后点击应用.

  9. 向左对齐的Gallery

    系统自带的Gallery选中的item总是在组件的中间.但是有些时候我们需要把选中的元素放在左边或者是Gallery一出来就要放在左边.修改Gallery靠左对齐的思路:1.Gellary总是对cen ...

  10. Unity3D研究院编辑器之Editor的GUI的事件拦截

    OnGUI是Unity上一个时代的UI系统,而现在运行时的UI系统已经被UGUI取代,但是Editor的UI还是在用老的这一套GUI系统.比如unity编辑器里的所有窗口,布局,按钮,拖动条.滚动等等 ...