【Scala八】Scala核心二:隐式转换

编程技术  /  houtizong 发布于 3年前   83

Implicits work like this: if you call a method on a Scala object, and the Scala compiler does not see a definition for that method in the class definition for that object, the compiler will try to convert your object to an instance of a class that does have that method defined

 

 

隐式转换是Scala类型系统的强大特性之一,使得静态类型动态化,为现有类库添加功能。Scala的隐式转换,有三种:

  • 隐式函数
  • 隐式参数
  • 隐式类

隐式转换的规则:

  • 如果代码无需隐式转换即可通过编译,则不会引入隐式转换
  • 隐式转换只会匹配一次,即隐式转换至多发生一次
  • 存在二义性的隐式转换报错,

 

 

在期望隐式转换发生作用的时候,必须告诉Scala编译器,隐式转换背后起作用的实现逻辑在哪里?这个实现逻辑称为作用域或者为上下文Context

 

一、隐式函数

 

增强一个类,添加本不存在的方法,implicit作用于函数,称之为隐式函数

 

package spark.examples.scala//假如Arithmetic是已有的类库中的类,仅仅提供add函数class Arithmetic {  def add(x: Int, y: Int): Int = {    x + y  }}//=========================================//下面是增强Arithmetic类,添加一个subtract方法//=========================================class RichArithmetic(val arithmetic: Arithmetic) {  def substract(x: Int, y: Int) = {    x - y  }}//转换的逻辑,隐式方法object ArithmeticToRichArithmetic {  //将Arithmetic转换为RichArithmetic  //Arithmetic对象上可以直接调用RichArithmetic定义的方法  implicit def arithmeticToRichArithmetic(arithmetic: Arithmetic) = {    new RichArithmetic(arithmetic)  }}object ImplicitDemo {  def main(args: Array[String]) {    import ArithmeticToRichArithmetic._ //引用方法    val a = new Arithmetic    println(a.add(11, 21))    println(a.substract(21,11)) //substract不属于Arithmetic  }}

 

 

二、隐式参数:

 

package spark.examples.scalaobject ObjectA {    def print(content: String)(implicit prefix : String) {      println(content + "," + prefix)    }}//ObjectA隐式转换的作用域object ObjectAWrapper {  implicit val DEFAULT_OBJECT_A_STRING = "ObjectA"}object ImplicitArgument {  def main(args : Array[String]) {    ObjectA.print("ABC")( "DEF")    import  ObjectAWrapper._ //Error: not enough argument if this line doesn't exist    //为String类型的参数隐式的提供DEFAULT_OBJECT_A_STRING值    ObjectA.print("ABC")    ObjectA.print("ABC")( "XYZ")  }}

 

隐式参数的应用

如下代码出错:

class A[T] {  def min(a: T, b: T) {    if (a < b) a else b //泛型类T没有定义<方法  }}object ImplicitArgument {  def main(args : Array[String]) {    val a = new A[Int]();    a.min(10,11)  }}

 

 

package spark.examples.scalaclass A[T] {  //这里相当于为T指定约束,即T必须能够隐式转换到Ordered  //T能够隐式转换到Ordered,那么对类型T的变量使用<操作时,将隐式地将T转换为Ordered类型的变量,然后调用Ordered类型的<方法  //T隐式转换到Ordered,需要预先定义  def min(a: T, b: T) (implicit  order: T=>Ordered[T]) = {    if (a < b) a else b  }}object ImplicitArgument2 {  def main(args : Array[String]) {    val a = new A[Int]();    println(a.min(10,11)) //Scala已经实现了Int到Ordered的隐式转换,否则3 < 4做不了    class B {}    /** 报错的原因是No implicit view available from B => Ordered[B].即B没有定义到Ordered的隐式转换,所以报错    val b = new A[B]() //    b.min(new B(), new B())    **/  }}

 

三、隐式类

增强一个类型

 

隐式类约束

  • 隐式类必须有一个带一个参数的主构造函数
  • 必须定义在另一个class/object/trait里面(不能独立定义)
  • 隐式类构造器只能带一个不是implicit修饰的参数
  • 作用域中不能有与隐式类类型相同的成员变量,函数以及object名称
package spark.examples.scalaclass B {  def add(x: Int, y: Int) = {    x + y  }}object ImplicitClassContext {  //隐式类,可以为一个类型(参数的类型)提供方法  //为主构造函数指定的类型进行增强  implicit class RichB(arg: B) {    def multiply(x: Int, y: Int) = {      x * y    }  }}object ImplicitClass {  def main(args: Array[String]) {    import ImplicitClassContext._    val b = new B();    println(b.multiply(3, 4))  }}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!

留言需要登陆哦

技术博客集 - 网站简介:
前后端技术:
后端基于Hyperf2.1框架开发,前端使用Bootstrap可视化布局系统生成

网站主要作用:
1.编程技术分享及讨论交流,内置聊天系统;
2.测试交流框架问题,比如:Hyperf、Laravel、TP、beego;
3.本站数据是基于大数据采集等爬虫技术为基础助力分享知识,如有侵权请发邮件到站长邮箱,站长会尽快处理;
4.站长邮箱:[email protected];

      订阅博客周刊 去订阅

文章归档

文章标签

友情链接

Auther ·HouTiZong
侯体宗的博客
© 2020 zongscan.com
版权所有ICP证 : 粤ICP备20027696号
PHP交流群 也可以扫右边的二维码
侯体宗的博客