scala详细笔记(十一)-scala高级语法之隐式详解

d通过隐式转换,程序员可以在编写Scala程序时故意漏掉一些信息,让编译器去尝试在编译期间自动推导出这些信息来,这种特性可以极大的减少代码量,忽略那些冗长,过于细节的代码。

  • 使得静态类型动态化
  • 为现有类库添加功能
  • 隐式的代理增强一个类或者一个方法

1. 隐式变量

使用 implicit修饰的变量称之为隐式变量 ,同一种类型的隐式变量在上下文中只能声明一个

object MyValue {
  implicit  val  age:Int = 19
  implicit  val name:String = "lisi"
}
/**
  * 这个方法的所有的参数是隐式参数
  * 可以使用柯里化来定义个别的隐式参数 
  * add(x:Int)(implicit y:Int , z:Int)
  *    上面的例子中x为正常参数 y z都为隐式参数
  * @param name
  * @param age
  */
def myShow(implicit name: String, age: Int): Unit = {
  println(name + "   " + age)
}

调用函数的时候可以不用写隐式类型的参数 , 会从上下文环境中获取 

def main(args: Array[String]): Unit = {
  new Show().myShow("reba",12)
  // 导入了隐式参数  就会从context中寻找隐式数据
  // context中只能有一个匹配类型的数据
  // 如果找到多个匹配类型的数据就会报错
 import  MyValue._
  //lisi   19
  new Show().myShow
}

隐式值可以为方法提供隐式参数

2 隐式函数

函数处理的数据类型 =>  返回的数据类型 , 当遇到对应的类型=>类型处理的时候隐式函数会自动的应用

增强一个类

添加不存在的函数,implicit作用于函数,称之为隐式函数

class A[T] {
 def mymax1(x:T ,y:T): T ={
    if(x > y) x else y// T类型中没有定义>方法  报错
  }
 // T类型必须是可以隐式的转换成Ordered的类型  , 这个隐式转换要事先定义
  def mymax2(x:T ,y:T)(implicit order:T=>Ordered[T]): T ={
    if(x > y) x else y
  }
}
object  A{
  def main(args: Array[String]): Unit = {
    // Int已经默认的实现了 Orderd的实时转换 
    val res: Int = new A[Int]().mymax2(12,34)
    println(res)
  }
}

 

/**
   * 定义一个隐式方法
   * 处理两个String类型返回一个String类型
   * @param str
   * @param str2
   * @return
   */
  implicit  def m(str:String, str2:String)={
    str.toUpperCase+"--"+str2.toUpperCase
  }

  /**
   * 定义一个方法  方法的第二个参数列表是一个隐式的函数为参数
   * @param str
   * @param f
   * @return
   */
  def m2(str:String)(implicit f:((String,String)=>String)): String ={
    f(str,str)
  }

  def main(args: Array[String]): Unit = {
   // 当调用方法的的时候 , 从上下文中找隐式函数, 直接饮用 
    println(m2("tom"))  //TOM--TOM

  }

3 隐式类(隐式视图)

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

隐式类约束

隐式类必须有一个带一个参数的主构造函数

必须定义在另一个class/object/trait里面(不能独立定义)

隐式类构造器只能带一个不是implicit修饰的参数

作用域中不能有与隐式类类型相同的成员变量,函数以及object名称

定义一个普通的类 只有一个add方法

class B {
  val add = (x: Int, y: Int) => {
    x + y
  }
}

定义一个隐式类

**
  * 隐式主题类
  */
object ImplicitContext{
//隐式类只能对一种类型的类进行增强  B类或者子类增强
  implicit  class RichB(b:B){
    def multiply(x: Int, y: Int) = {
      x * y
    }
  }
}

效果  B类中具有了隐式类中的multiply()方法

def main(args: Array[String]): Unit = {
  val b = new B   // B类  以及他的子类
  println(b.add(12, 12))
  import ImplicitContext._
  println(b.multiply(12, 12))
}

如果代码无需隐式转换即可通过编译,则不会引入隐式转换

隐式转换只会匹配一次,即隐式转换至多发生一次

存在二义性的隐式转换报错,

列子增强File类 , 具有读取行数据的能力

/**
 * @Auther: 多易教育-行哥
 * @Date: 2020/6/27 
 * @Description: 
 */
object TestIm {

  implicit class RichFile(file: File) {
    def getLines() = {
      Source.fromFile(file).getLines()
    }
  }

  def main(args: Array[String]): Unit = {
    val file = new File("d://data/app.txt")
    // 如果没有上面的隐式类, file中是没有getlines方法的
    file.getLines().foreach(println)
  }
}

猜你喜欢

转载自blog.csdn.net/qq_37933018/article/details/106982819