scala的隐式对象和隐式类

64 阅读3分钟

隐式对象

定义:

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

示例代码:

case class DatabaseConfig( driver: String, url: String)

implicit object MySqlDefaultConfig extends DatabaseConfig(
  "com.mysql.cj.jdbc.Driver",
  "jdbc:mysql://localhost:3306/mydb")

def getConnection(implicit config: DatabaseConfig): Unit = {
  println(config.url)
}
getConnection

隐式类

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

  • 思路:

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

示例代码:

/*
目标:已有一个写好的类,要求在不修改这个类的源代码的情况下,拓展这个类的新功能
思路:
    1.补充定义一个新类,在这个新类中提供新方法
    2.提供一个隐式转换函数,把之前旧类对象转换成这个新类对象
 */
object day53 {
  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 不能放在顶级作用域(不能放在类的外边)看如下代码,就会报错

implicit class UserExt(user: User) {  
  def updateUser(): Unit = {  
    println("updateUser")  
  }  
}  
class User {  
  def insertUser(): Unit = {  
    println("insertUser")  
  }  
}  
object T1 extends  OtherClass {  
  def main(args: Array[String]): Unit = {  
    val u1 = new User()  
    u1.insertUser()  
    u1.updateUser()  
  }  
}

在实际的操作过程中,我们建议把它定义在如下两个地方:

  1. 包对象。这样在这个包下的所有类和对象中都可以使用,并且不需要额外的引入语句。
  2. 一个单独的文件定义中。这样在其他需要的位置就可以直接导入,然后使用。
package implications  
object Implications{  
  implicit def double2Int (x: Double):Int { x.toInt   }  
}

在其他需要使用的地方导入: import implication.Implications._

案例:

一个字符串具备一个功能,判断是否是一个合法的手机号

/*
目标:让人一样一个字符串具备一个功能,判断是否是一个合法的手机号
String类是系统提供的,并没有isPhone()方法
现在要在不修改String类的情况下,添加这个方法
 */
object day54 {
  implicit class StrongString(s:String) {
    def isPhone:Boolean={
      val reg="^1[35678]\\d{9}$".r
      reg.matches(s)
    }
    def isIDCard: Boolean = {
      val Reg1 = "^[1-9]\\d{5}(18|19|20)\\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$".r
      Reg1.matches(s)
    }
  }

  def main(args: Array[String]): Unit = {
   val str=new String("13827339067")
    println(str.isPhone)
    println("134567891a".isPhone)
    println("130567891a".isPhone)
    println("421022200901203625".isIDCard)
    println("42102220070118368a".isIDCard)
  }
}

运行结果如下:

true
false
false
true
false

让任意一个整数具备一个功能:计算阶乘

package imp
import scala.language.postfixOps
object day55 {
  /*
   目标:让任意一个整数具备一个功能:计算阶乘
   */
  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
  }
}

运行结果如下:

24
120