Scala—隐式对象和隐式类

14 阅读3分钟

一、隐式对象

隐式对象是一个带有implicit关键字的单例对象,它可以用于提供某种类型的实例以供隐式转换使用。隐式对象通常用于将某个类或trait的实例隐式地注入到方法中。

隐式对象和前面讲的隐式参数比较类似,都是用来设置初始数据的。

二、隐式类

  • 目标:已有一个写好的类,要求在不修改这个类的源代码的情况下,拓展这个类的新功能!

思路:

  • 1.补充定义一个新类,在这个新类中提供新方法;
  • 2.提供一个隐式转换函数,把之前旧类对象转换成这个新类对象。
object imp04 {

  class User() {
    def insertUser():Unit = {
      println("insertUser......")
    }
  }

  class UserStrong() {
    def updateUser():Unit = {
      println("updateUser......")
    }
  }

  implicit def xxxxx(user:User):UserStrong = {
    println("自动调用隐式转换函数......")
    new UserStrong
  }

  def main(args: Array[String]): Unit = {
    val u1 = new User()
    u1.insertUser()
    // val u2 = new UserStrong()
    u1.updateUser()
    // u2.updateUser()
  }

}

隐式类: implicit class

  • 作用:在不修改原来的基础之后,增加新的功能。
  implicit class UserStrong(user:User) {
    def updateUser():Unit = {
      println("updateUser......")
    }
  }

//  implicit def xxxxx(user:User):UserStrong = {
//    println("自动调用隐式转换函数......")
//    new UserStrong
//  }

三、案例:验证字符串是否邮箱

需求说明:给字符串补充一个功能,验证它是否是一个邮箱?

在开始去写代码之前,请大家想回答如下三个问题:

1. 字符串方法本身是否就具有isEmail方法?

2. 如果字符串本身不具备这个方法,我们是可以写一个自定义的类StrongStr,并封装这个isEmail方法?

3. 假设已经有这个类了,我们是否可以写一个转换函数,把String类转成StrongStr?

4. 这个转换函数是否可以隐式被调用?

补充一个隐式类,它的功能是:接收一个字符串,得到一个对象,这个对象就有这个isEmail方法。

  • 目标:让任意一个字符串具备一个功能:判断是否是一个合法的手机号。

  • String类是系统提供的,并没有isPhone这个方法。

  • 现在就要去在不修改String类的情况下,增加这个方法。

  implicit class StrongString(s:String) {
    def isPhone:Boolean = {
      val reg = "^1[35678]\d{9}$".r
      reg.matches(s)
    }
  }


  def main(args: Array[String]): Unit = {
    val str = new String("12435435231")
//    val str = "12435435231"
//    str.isPhone()  // 判断自己是一个合法的手机号,返回值是boolean。true,false

    println(str.isPhone)
    println("12435435231".isPhone)
    println("12435435231".isPhone)

  }

四、计算阶乘

需求说明:给一个所有的整数添加一个功能,例如:3!=321。

·println(3!) // 输出6

思路分析:与上面的增强版字符串一样,我们这的整数是增强版的整数。

请特别注意implicit class

目标: 让任意一个字符串具备一个功能:计算阶乘。

  • n! = 123*...*n
  • 5! = 1 * 2 * 3 * 4 * 5 = 120
import scala.language.postfixOps

object imp06 {
  implicit class StrongInt(n:Int) {
    def ! :Int = {
      var rst = 1
      for(i <- 1 to n) {
        rst *= i
      }
      rst
    }
  }

  def main(args: Array[String]): Unit = {
    println(4!)  // 24
    println(5!)  // 120
  }
}