scala的隐式对象和隐式类

29 阅读2分钟

(一)隐式对象

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

package imp

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()
  }
}

(二)隐式类

【背景】有一个现有的类。现在我们需要对这个类的功能进行拓展,额外补充一个方法。但是,不允许直接修改原来的类的代码。

假设这里有一个类User,它的内部有一个方法 insertUser

class User {  
  def insertUser(): Unit = { println("insertUser") }  
}  
def main(args: Array[String]): Unit = {  
  val u1 = new User()  
  u1.insertUser()

}

这个程序运行起来非常的稳定了,同时又不要去改动它之前的代码。 我们的基本思路是:再写一个类,然后在其中补充一个方法,然后让当前的类去使用这个方法。

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

需求说明:给字符串补充一个功能,验证它是否是一个邮箱?具体来讲就是确保如下代码能正常工作。

package imp
/*
目标:让任意一个字符串具备一个功能:判断是否是一个合法的手机号。
String 类是系统提供的,并没有 isPhone 这个方法。
现在就要去在不能修改 String 类的情况下,增加这个方法。
 */
object imp05 {

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


    def isIDCard: Boolean = {
      val reg = "^\d{17}[0-9Xx]$".r
      reg.matches(s)
    }
  }

  def main(args: Array[String]): Unit = {
    val str = new String("13617295643")
    // val str = "13617295643"

    // 判断是否是合法手机号,返回Boolean
    println(str.isPhone)
    println("134567891a".isPhone)     // false
    println("130567891a".isPhone)     // false
    println("490005202010110223".isIDCard)  // true(假设符合18位格式)
    println("490005202010110223a".isIDCard)  // false
  }
}

(四)案例:计算阶乘

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

println(3!) // 输出6

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

import scala.language.postfixOps

/*
目标: 让任意一个整数具备一个功能: 计算阶乘
n! = 1*2*3*...*n
5! = 1 × 2 × 3 × 4 × 5 = 120
*/
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
  }
}