隐式转换
我们需要某个类中的一个方法,但是这个类没有提供这样的一个方法,所以我们需要隐式转换,转换成提供了这个方法的类,然后再调用这个方法
第一步,需要一个增强的类,里面提供我们想要的方法,接收的参数的类型一定要是被增强类的类型。
第二部,还需要在单例对象中写明隐式转换
第三步,把隐式转换函数导进来
在spark中隐士转换都写在伴生对象中,因为类的实例肯定能找到伴生对象的,在一个作用域当中
import scala.io.Sourceimport java.io.File //这里的RichFile相当于File的增强类 需要将被增强的类作为参数传入构造器中class RichFile(val file: File) { def read = { Source.fromFile(file.getPath).mkString } } //implicit是隐式转换的关键字 这里定义一个隐式转换函数把当前类型转换成增强的类型object Context { //File --> RichFile implicit def file2RichFile(file: File) = new RichFile(file) } object Hello_Implicit_Conversions { def main(args: Array[String]): Unit = { //导入隐式转换 import Context.file2RichFile //File类本身没有read方法 通过隐式转换完成 //这里的read方法是RichFile类中的方法 需要通过隐式转换File --> RichFile println(new File("E:\\projectTest\\1.txt").read) } }
隐式参数
object Context_Implicits { implicit val default: String = "Java"} object Param { //函数中用implicit关键字 定义隐式参数 def print(context: String)(implicit language: String){ println(language+":"+context) } } object Implicit_Parameters { def main(args: Array[String]): Unit = { //隐式参数正常是可以传值的,和普通函数传值一样 但是也可以不传值,因为有缺省值(默认配置) Param.print("Spark")("Scala") //Scala:Spark import Context_Implicits._ //隐式参数没有传值,编译器会在全局范围内搜索 有没有implicit String类型的隐式值 并传入 Param.print("Hadoop") //Java:Hadoop } }
隐式参数与隐式转换
object Implicit_Conversions_with_Implicit_Parameters { def main(args: Array[String]): Unit = { /** * (1)bigger[T]为泛型函数 * (2)bigger(...)(...)该函数是柯里化的 * (3)第二个括号传入的是一个匿名函数,类型为T => Ordered[T] orders是隐式参数 输入类型为T类型, 返回类型为Ordered[T]类型 * * */ def bigger[T](a: T, b: T)(implicit ordered: T => Ordered[T]) = { /** * ordered(a) > b中的">"是一个函数 具体定义在Ordered类中 * Source define: * def > (that: A): Boolean = (this compare that) > 0 */ if (ordered(a) > b) a else b // if (a > b) a else b 这样写也可以 } println(bigger(4, 3)) //4 println(bigger("Spark", "Hadoop")) //Spark } }
上下文界定中的隐式参数
在每次上下文运行的实例对象中将具体的值注入到隐式参数中,而且注入的过程是自动的
//[T: Ordering]:说明存在一个隐式类型Ordering[T]class Pair_Implicits[T: Ordering](val first: T, val second: T){ //声明一个隐式类型对象传入函数 def bigger(implicit ordered: Ordering[T]) = { if (ordered.compare(first, second) > 0) first else second } }//简化上面的写法class Pair_Implicitly[T: Ordering](val first: T, val second: T){ def bigger = if (implicitly[Ordering[T]].compare(first, second) > 0) first else second }//进一步简化class Pair_Implicitly_Ordereded[T: Ordering](val first: T, val second: T) { def bigger = { import Ordered._ if (first > second) first else second } } object Context_Bounds_Internals { def main(args: Array[String]): Unit = { println(new Pair_Implicits(7, 9).bigger) println(new Pair_Implicitly(7, 9).bigger) println(new Pair_Implicitly_Ordereded(7, 9).bigger) } }
隐式类
有时候进行代码重构,要增强他的某项功能同时又不想做太大的改动
更多用的是隐式转换,隐式类用的不多
import scala.io.Sourceimport java.io.File object Context_Helper { implicit class FileEnhancer(file: File) { def read = Source.fromFile(file.getPath).mkString } implicit class Op(x: Int) { def add(second: Int) = x + second } } object Implicits_Class { def main(args: Array[String]): Unit = { import Context_Helper._ /** * File对象中并没有read方法 编译器会在全局范围内查询匹配的隐式类 * 在Context_Helper导入的类中有FileEnhancer 接受File类型的类 会自动匹配 、 * 使得File对象通过这种隐式的方法具有read方法 */ println(new File("E:\\projectTest\\1.txt").read) println(1.add(2)) //3 } }
隐式对象
abstract class Template[T] { def add(x: T, y: T): T }abstract class SubTemplate[T] extends Template[T] { def unit: T } object Implicits_Object { def main(args: Array[String]): Unit = { implicit object StringAdd extends SubTemplate[String] { def add(x: String, y: String): String = x concat y def unit: String = "" } //定义隐式对象 定义方式:implicit object XXX implicit object IntAdd extends SubTemplate[Int] { def add(x: Int, y: Int): Int = x + y def unit: Int = 0 } //implicit m: SubTemplate[T]中 m是一个隐式对象就是实际在运行的对象 def sum[T](xs: List[T])(implicit m: SubTemplate[T]): T = if (xs.isEmpty) m.unit else m.add(xs.head, sum(xs.tail)) println(sum(List(1, 2, 3))) //6 println(sum(List("Scala", "Spark", "Kafka"))) //ScalaSparkKafka } }
通过伴生对象进行隐式转换
import java.io.Fileimport scala.io.Source class RichFile(val file: File) { def read = Source.fromFile(file.getPath).mkString } class File_Impkicits(path: String) extends File(path) object File_Impkicits { implicit def file2RichFile(file: File) = new RichFile(file) //file-->RichFile} object Implicits_Internals { def main(args: Array[String]): Unit = { /* * 这里没有导入隐式对象 * * 通过给File_Impkicits类 构建一个伴生对象 在伴生对象内部顶一个隐式转换的方法 * * 执行顺序: * 1.搜索File_Impkicits有无read方法 * 2.在上下文上搜索(有无导入的隐式对象) * 3.搜索File_Impkicits的伴生对象内有无隐式转换 发现implicit关键 尝试匹配类型 * 例如这里匹配file2RichFile(file: File) 返回类型为RichFile 在RichFile中发现read方法 */ println(new File_Impkicits("E:\\projectTest\\1.txt").read) } }
作者:他与理想国
链接:https://www.jianshu.com/p/ebbb148e5fd6
点击查看更多内容
为 TA 点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦