a32_scala 隐式转换 隐式函数 隐式参数 隐式类

scala outline

scala outline

scala 隐式转换

scala中通过implicit关键字修饰的变量、函数或者类,在调用时,不用显式书写调用过程的一种语法

隐式转换目的:
扩展功能

scala 隐式转换触发时机

当想调用对象功能时,如果编译错误,那么编译器会尝试在当前作用域范围内查找是否有对应功能的转换规则,如果有,编译器会自动调用这个转换规则

scala 手动导入隐式函数

隐式函数: 指的是用 implicit关键字 声明的带有 单个参数 的方法,该方法是被自动调用的,用来实现 自动将某种类型的数据转转换为另外一种类型的数据

需求:通过隐式转换, 让File类的对象(File类的对象不具有read功能)具备有read功能,即: 实现将文本中的内容以字符串形式读取出来

import java.io.File
import scala.io.Source

// 1. 定义一个RichFile类, 用来给普通的File对象添加 read()功能
class RichFile(file: File) {
  // 定义一个read()方法,用来读取数据
  def read(): String = {
    Source.fromFile(file).mkString
  }
}

// 2. 定义一个单例对象,包含一个方法,该方法用于将:普通的File对象 转换成 RichFile对象
object Demo {
  //定义一个方法, 该方法用于将: 普通的File对象 转换成 RichFile对象
  implicit def file2RichFile(file: File): RichFile = {
    new RichFile(file)
  }
}

object Test01 {

  def main(args: Array[String]): Unit = {
    // 3. 非常重要的地方: 手动导入 隐式转换
    import Demo.file2RichFile
    // 4. 创建普通的File对象, 尝试调用其read()功能
    val file = new File("E:\\input\\hello.txt")
    /*
    执行流程:
       1. 先找File类有没有read(), 有就用
       2. 没有,就去查看是否有该类型的隐式转换,将该对象转成其他对象
       3. 如果没有隐式转换, 直接报错
       4. 如果可以将该对象升级为其他对象, 则查看升级后的对象中有没有指定方法, 有, 不报错, 没有就报错
    如下的案例执行流程:
        1. file对象中没有read()方法
        2. 检测到有隐式转换将 file对象 转成 RichFile对象
        3. 调用RichFile对象的read()方法,打印结果
     */
    println(file.read())
  }
}

scala 自动导入隐式函数

import java.io.File
import scala.io.Source

// 1. 定义一个RichFile类, 用来给普通的File对象添加 read()功能
class RichFile(file: File) {
  // 定义一个read()方法,用来读取数据
  def read(): String = {
    Source.fromFile(file).mkString
  }
}

object Test01 {
  def main(args: Array[String]): Unit = {
    // 2. 自定义一个函数, 该函数用implicit修饰,用来将: 普通的File -> RichFile, 当程序需要使用的时候, 会自动调用
    implicit def file2RichFile(file: File): RichFile = {
      new RichFile(file)
    }

    // 3. 创建File对象, 调用read()方法
    val file = new File("E:\\input\\hello.txt")
    println(file.read())
  }
}

scala 隐式参数

隐式参数: 指的是用 implicit关键字 修饰的变量

普通方法或者函数中的参数可以通过implicit关键字声明为隐式参数,调用该方法时,编译器会在相应的作用域寻找符合条件的隐式值

  def main(args: Array[String]): Unit = {
    implicit val str: String = "cuihua"

// 函数中的参数name可以通过implicit关键字声明为隐式参数
    def say(implicit name: String): Unit = {
      println("hello:" + name)
    }
    say // 调用该方法时,编译器会在相应的作用域寻找符合条件的隐式值str
  }

注意:

  1. 同一个作用域中,相同类型的隐式值只能有一个
  def main(args: Array[String]): Unit = {
    implicit val str: String = "cuihua"
    implicit val str1: String = "fengjie" // 错误 同一个作用域中,相同类型的隐式值只能有一个

    def say(implicit name: String): Unit = {
      println("hello:" + name)
    }
    say
  }

输出

hello:cuihua
  1. 隐式参数优先于默认参数
  def main(args: Array[String]): Unit = {
    implicit val str: String = "cuihua"

    def say(implicit name: String="fengjie"): Unit = {
      println("hello:" + name)
    }
    say // 输出:hello:cuihua
  }

scala 隐式类

Scala2.10后提供了隐式类,可以使用implicit声明类,隐式类的非常强大,同样可以扩展类的功能,在集合中隐式类会发挥重要的作用

(1)其所带的构造参数有且只能有一个

(2)隐式类必须被定义在“类”或“伴生对象”或“包对象”里,即隐式类不能是顶级的

import java.io.File
import scala.io.Source

object Test01 { // 隐式类 RichFile 被包裹在伴生对象 Test01 中
  implicit class RichFile(file: File) {
    def read(): String = {
      Source.fromFile(file).mkString
    }
  }

  def main(args: Array[String]): Unit = {
    val file = new File("E:\\input\\hello.txt")
    println(file.read())
  }
}

隐式解析机制

  1. 首先会在当前代码作用域下查找隐式实体(隐式方法、隐式类、隐式对象)
  2. 如果第一条规则查找隐式实体失败,会继续在隐式参数的类型的作用域里查找

例如 隐式参数使用的优先顺序为:

(1)当前类声明的implicits
(2)导入包中的 implicits
(3)外部域(声明在外部域的implicts)
(4)继承的父类中的
(5)所属包对象中的
(6)伴生对象的以上作用域

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值