• 0

  • like

  • Favorite

Scala之隐式转换

1 year ago

啥是隐式转换?

我们需要某个类中的一个方法,但是这个类没有提供这样的一个方法,所以我们需要隐式转换,转换为提供了该方法的类后,该类则变为了原来的类的增强类。某个类+该类不具备的方法->增强类

举个例子:一个普通人people拥有吃饭、睡觉等基本方法,当people这种普通人有一天想要变成一位猛男时,按照我们之前的思路则应该为这个普通人添加一个muscleMan的方法或者去继承猛男类来获得猛男的方法。但这种实现方式针对有些特殊场景并不适用,如:

  • 1)如果猛男这个类是黑盒的,你如何去为普通人people添加一个已有的猛男方法呢?
  • 2)如果你频繁的去使用继承的方式,是否又忽略了开发的原则。高内聚,低耦合?

所以在此引出implicit这个概念,下文将逐步带你领略implicit的魅力。

隐式转换的实现方式

  • 1)将方法或类型标记为implicit
  • 2)将类标记为implicit
  • 3)将方法的参数列表标记为implicit(这个不常用)

将方法标记为implicit

Biliking由于是通过Pepole类new出来的对象,所以它只会吃喝,并不是个猛男

object Myimplicit {
  def main(args: Array[String]): Unit = {
    //比利王从前也是个普通人
    val BiliKing = new People("比利王")
    BiliKing.

  }
}

class People(val name: String){

  def eat():Unit = {
    println(s"$name 吃饭了")
  }

  def sleep():Unit = {
    println(s"$name 睡觉了")
  }

}
复制代码

我们现在需要通过隐式转换让比利得到成为猛男的方法

//把普通人放进去,返回一个SuperMan
    implicit def peopleToSuperMan(people: People):SuperMan = {
      new SuperMan(people.name)
    }
复制代码

最终代码:

object Myimplicit {
  def main(args: Array[String]): Unit = {
    //比利王从前也是个普通人
    val BiliKing = new People("比利王")

    //把普通人放进去,返回一个SuperMan
    implicit def peopleToSuperMan(people: People):SuperMan = {
      new SuperMan(people.name)
    }
    
    //通过隐式转换后,所有从Peope创建的对象都将拥有muscleMan()的方法,比利也从此变成了一个猛男
    BiliKing.muscleMan()

  }
}
class People(val  name: String){

  def eat():Unit = {
    println(s"$name 吃饭了")
  }

  def sleep():Unit = {
    println(s"$name 睡觉了")
  }

}
class SuperMan(val name: String){

  def muscleMan():Unit = {
    println(s"$name 变成了个大猛男")
  }

}
复制代码

将类标记为implicit

object Myimplicit {
  def main(args: Array[String]): Unit = {
    //比利王从前也是个普通人
    val BiliKing = new People("比利王")

    BiliKing.muscleMan()

  }
  //通过隐式转换后,所有从Peope创建的对象都将拥有muscleMan()的方法,比利也从此变成了一个猛男
  implicit class ChangeMuscleMan(people: People){
    def muscleMan():Unit = {
      println(s"${people.name} 变成了个大猛男")
    }
  }
  
}
class People(val  name: String){

  def eat():Unit = {
    println(s"$name 吃饭了")
  }

  def sleep():Unit = {
    println(s"$name 睡觉了")
  }

}

复制代码

将类型标记为implicit

以int类型为例,为所有int类型增强一个加减乘的方法aSM

object Myimplicit {
  def main(args: Array[String]): Unit = {
    1.aSM("add", 1)
    10.aSM("sub", 1)
  }

  //定义一个隐式转换,类型为int
  implicit class AddSubXAvg(x:Int){
    //模式匹配
    def aSM(input:String ,value:Long):Long = input match {
      case "add" => x + value
      case "sub" => x + value
      case "X" => x + value
    }
  }
}
复制代码

将方法的参数列表标记为implicit

默认情况下,这个参数是必填的,如果不填就会报错

object Myimplicit {
  def main(args: Array[String]): Unit = {

    val yy = new People("YY哥")
//    yy.eat

    implicit val lala = 2
    yy.eat

  }
}
class People(val name: String){

  def eat(implicit eatHowMuch:Int):Unit = {
    println(s"$name 吃饭了 吃了$eatHowMuch 大碗")
  }

}
复制代码

注意:如果出现多个intimplicit,程序时反应不过来的。所以仅能有一个变量值被隐式转换

隐式转换的滥用问题

建议单独做一个隐式转换切面,所有的隐式转换都放在类中,如下所有隐式转换都在implicitGuiDang中。哪里需要用到时,请在需要使用的类中导入implicitGuiDang即可

object implicitGuiDang{

  implicit class AddSubXAvg(x:Int){
    
    //模式匹配
    def aSM(input:String ,value:Long):Long = input match {
      case "add" => x + value
      case "sub" => x + value
      case "X" => x + value
    }
  }
}
复制代码

隐式转换的作用域问题

  • 有些情况下,隐式转换需要提到代码块的最上面才可以
  • 隐式转换可以定义在伴生对象中,隐式转换会去相关类的伴生对象中去找,例如:去pepole以及猛男类中找
免责声明:文章版权归原作者所有,其内容与观点不代表Unitimes立场,亦不构成任何投资意见或建议。

java

0

Relevant articles

未登录头像

No more data