欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

[Scala] Scala 学习笔记 (11) - 隐式转换

程序员文章站 2022-06-15 12:09:02
...

隐式转换

隐式转换在工作中,能不用就不用,读代码难度很大,不利于team work。

 

场景:已有一个类,要基于这个类添加一个方法。

Java的实现思路:

如果要添加的方法很少,用继承或者装饰可以完成。

如果要添加的方法很多,最好的方法是使用代理。其中代理又分静态代理和动态代理:

静态代理:持有

动态代理:JDK,代理的是一个接口; CGLIB: 是一个类

Scala的实现思路:

隐式转换:即偷偷地,不知不觉地给你干了点啥。增强方法。

 

Scala代码实现:

示例一:普通狗转成牛逼的狗

定义一个普通的类

// 定义一个普通的狗
class Dog(val name:String)

再定义一个有属性有方法的类

// 再定义一个特殊的狗,这个类比上面的多一些属性和方法
class JoeyDog(val name:String) {
  def speak(): Unit = {
    println("wang wang wang.")
  }
}

隐式转换

将普通的狗转换成牛逼的狗,这样普通的狗就可以调用牛逼的狗的方法了

object ImplicitApp {

  def main(args: Array[String]): Unit = {

    // 定义隐式转换函数: 普通2牛逼/普通To牛逼
    // implicit 是一个
    // 传进去一只普通狗,出去的时候是牛逼的狗
    // 做法是new一个牛逼的狗,把普通狗的名字传进去
    implicit def dog2JoeyDog(dog:Dog):JoeyDog = new JoeyDog(dog.name)

    // 此时再new一个普通的狗出来,这条普通的狗就可以调用牛逼的狗的方法了
    val dog = new Dog("Dog A")

    dog.speak()
  }

}

示例二:为Java的File类添加一个read方法

/**
  * Java里面有一个File类,为File添加一个read方法可以直接读取内容
  * 我们不能直接修改源码,通常可以通过隐式转换来实现
  * 定义的RichFile类要把File类传进去
  */
class RichFile(val file:File) {

  def read() = {
    Source.fromFile(file.getPath).mkString
  }

}

隐式转换,让File可以调用RichFile里面新添加的read方法

import java.io.File

import scala.io.Source

object FileImplicitApp {
  def main(args: Array[String]): Unit = {
    /**
      * 定义一个隐式转换函数,把普通的File转成丰富的RichFile
      * 其中File是java.io.File
      *
      */
    implicit def file2RichFile(file:File):RichFile = new RichFile(file)

    val file = new File("test.txt")
    val content = file.read()
    println(content)
  }

}

生产正确示例:整合ImplicitAspect类

以上两个示例阐明了隐式转换函数的用法,但是在实际生产中,上面的写法是比较忌讳的的。隐式转换函数的作用域是整合项目,隐式转换函数分散在各个文件中非常难找。通常的做法是抽取一个类(ImplicitAspect)出来,单独存放所有的隐式转换函数。

抽取一个ImplicitAspect类出来,把原来的隐式转换函数都移到这个类当中(原来各个类里面的隐式转换函数删除)

import java.io.File


// 这个类专门用来存放隐式转换函数
object ImplicitAspect {

  // 把上面两个示例中的隐式转换函数拷贝过来,把原来scala类里面的隐式转换函数删除
  implicit def file2RichFile(file:File):RichFile = new RichFile(file)
  implicit def dog2JoeyDog(dog:Dog):JoeyDog = new JoeyDog(dog.name)

  // 回到原来的文件中,import ImplicitAspect._ 即可

}

再回到原来的scala类中,添加一句话

import ImplicitAspect._

这样,原来的代码又可以正常运行了。

 

Spark的RDD源码里有很多隐式转换,可以参考。

相关标签: scala 隐式转换