您的位置:首页 > 其它

深入理解Scala中的隐式转换系统

2016-11-02 11:24 204 查看
博客核心内容:

1、Scala中的两种隐式转换机制以及隐式视图的定义方式

2、Scala中的隐式绑定可能所处的位置以及如何更好的使用隐式转换

3、Scala中的隐式转换相关操作规则

4、Scala中的隐式参数

5、Scala中的隐式类

6、Scala中的隐式对象

7、Scala中的两种隐式类型约束(结合Scala中的类型系统)

8、Predef类中的implicitly方法的用法介绍以及Ordering类型转化为Oredered类型的方式

1、Scala中的两种隐式转换机制以及隐式视图的定义方式
⑴Scala支持两种形式的隐式转换机制—-隐式值和隐式视图:

①隐式值可以用于给方法提供参数

②隐式视图是指把一种类型自动转换成另外一种类型,进而使用另外一种类型中的属性和方法,从而满足表达式的要求.

隐式视图的定义一般用如下形式:



作用:如果在隐式作用域里存在这个定义,它会隐式地把原始类型的值转换为增强之后的类型的值(在需要的时候).

⑵隐式值和隐式视图都采用相同的隐式解析机制,所谓隐式解析是指如果编译器发现代码里缺少部分信息,进而查找缺失信息的过程。在Scala当中,隐式解析一般分为两个阶段:在隐式转换的作用域查找中,如果当前作用域没有隐式转换,编译器会自动到相应源或目标类型的伴生对象中查找隐式转换。

⑶在Scala当中,隐式视图即隐式函数的命名一般这样写:前面是转换之前的类型,后面是增强之后的类型,如int2Integer。并且函数的参数一般是转换之前的类的实例,函数的执行体就是创建一个增强类对象.



⑷在隐式视图中,增强类的主构造器的参数类型一般是转换之前的类的类型,并且增强类中含有我们想要的方法。

示例程序1:



2、Scala中的隐式绑定可能所处的位置以及如何更好的使用隐式转换
⑴在应用隐式系统时最重要的一点是确保程序员能够理解一块代码里发生了什么。要做到这点就必须缩小程序员查找可用的隐式值的时候需要看到的代码的范围。隐式绑定可能所处的位置:

①所有关联类型的伴生对象,包括包对象:即Scala会在关联类型的伴生对象中寻找隐式值,这种行为是Scala语言的核心.

②Scala.Predef头文件中:每个编译后的Scala文件的开头都有一句:



Predef头文件中包含很多有用的转换方法,比如在Scala.Predef头文件中有个java.lang.Integer =>scala.Int的隐式转换.

③作用域里的所有导入语句:最后一个隐式转换可能存在的位置是源代码里明确的import导入语句.

⑵Scala当中如何更好的使用隐式转换:通过伴生类与伴生对象机制,编译器将会自动导入隐式转换, 而无需用户手动导入隐式转换。

实例程序1:



实例程序2:



3、Scala中的隐式转换相关操作规则
①在Scala当中,要想使用隐式转换,必须标记为implicit关键字,implict关键字可以用来修饰参数(隐式值与隐式参数)、函数(隐式视图)、类(隐式类)、对象(隐式对象).

②隐式转换在整个作用域中,必须是单一的标识符,进而避免隐式冲突.

③在隐式转换的作用域查找中,如果当前作用域没有隐式转换,编译器就会自动到相应源或目标类型的伴生对象中查找隐式转换。

④Scala中的隐式值、隐式类、隐式对象常放在单例对象object中.

实例程序1:



4、Scala中的隐式参数
①在Scala当中,所谓隐式参数就是在函数或方法中的参数前面加上implicit修饰符,这样的参数叫做隐式参数.

②隐式参数提供了很棒的机制,让用户无需指定冗余的参数.

③在Scala当中,若在函数的参数前面含有implicit修饰符,编译器就会自动寻找相应的隐式值作为默认值(缺省值)进行传递。



5、Scala中的隐式类
①Scala中的隐式类就是在普通类的前面加上一个implicit关键字,并修改相应的主构造器,主构造器的参数类型一般是转换之前的类的类型,最后在隐式作用域内导入即可。Scala中的隐式类是对类功能增强的一种形式.

②Scala中的隐式视图是在转换之前的类的伴生对象中做文章,而Scala中的隐式类是在增强的类中做文章,因为前者不用手动导入,所以Scala中的隐式类相比于隐式视图用的较少.

③单例对象中可以构建静态的属性和方法,还可以构建静态的类,若想使用单例对象中的静态类,import导入即可。

实例程序1:



6、Scala中的隐式对象
①Scala中的隐式对象就是在object对象前面加上implicit修饰符,隐式对象在某种程度上而言可以作为隐式值进行使用.

②在Scala当中,标注类型的时候可以直接用类和特质的名字来引用其类型,而要引用对象的类型,需要用对象的type成员来引用其类型,而不能直接用object的名字来引用其类型,主要是为了区别伴生对象和伴生类.

实例程序1:



7、Scala中的两种隐式类型约束(结合Scala中的类型系统)
⑴Scala支持两种特殊的类型约束操作符,它们其实不是真正的类型约束而是隐式查找,这两种操作符就是上下文界定和视图界定。这些操作符允许你定义一个隐式参数列表来作为泛型类型的类型约束。在隐式转换定义必须可被查找到但不需要直接访问的情况下,这种语法可以让你少打点字。隐式类型约束的两种类型分别是视图界定(涉及到了隐式视图)和上下文界定(隐式值)。

①视图界定用来”要求”一个可用的隐式视图(内部机制)来将一种类型自动转换成另外一种类型。隐式视图的定义如下:



含义:foo方法定义了一个约束 A <% B,意思是参数x的类型为A,并且在调用的地方必须存在相应的隐式转换 A=>B,可以用下面的写法表达出同样的意思:



这个foo方法也可以用一个不带类型约束的类型参数来定义。有两个参数:一个接受一个A类型的参数,第二个接受一个隐式转换函数。尽管第二种形式要打更多字,但是他给隐式转换函数打了个用户自定义的标签。

②上下文界定用来”要求”一个可用的隐式值存在,且必须存在。上下文界定如下:



foo方法定义了约束A:B,这个约束的含义是参数x的类型为A,并且调用foo方法时必须有一个可用的隐式值B[A]存在,上下文界定可以重新这样写:



这个foo方法定义了两个参数,其隐式参数接受一个B[A]类型的值。尽管第二种形式要打更多字,但是他给隐式值打了个用户自定义的标签。

实例程序1:



实例程序2:



实例程序3:



运行结果:

Spark
Ordering[String]
Ordering[java.lang.Integer]


从实例程序3我们可以看出,在Scala当中Ordering[String]与Ordering[java.lang.Integer]这种类型确实存在,同时我们也可以通过下面的方式进行进一步的确定:



8、Predef类中的implicitly方法的用法介绍以及Ordering类型转化为Oredered类型的方式
①Predef类中的implicitly方法可以获取参数实际运行时具体的数值:



②Ordered的伴生对象中含有很多内容:其中一个就是将Ordering数据类型隐式的转化为Oredered类型:



实例程序1:



实例程序2:



如有问题,欢迎大家留言指正!!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: