Scala隐式转换、隐式参数、隐式方法、implicit关键字修饰方法变量(参数)、隐式转换的时机、隐式转换和隐式参数案例 26

    xiaoxiao2024-11-22  71

    前言

    隐式转换就是,让某一个类具有另一个class(或者另一个object)的方法/参数值。

    隐式参数&隐式方法 隐式参数,用一个类型的隐式参数只能定义异常implicit修饰隐式值或者有方法相应触发隐式转换,需要在使用处导入import object名称.隐式参数/隐式方法名称 只能定义在object中让class A具有class B的功能 implicit aToB(a:A) = new B(a.属性值)调用时需要导入类名.方法名,import myImplicit.aToB 隐式转换后,让class A具有多个类的同一个方法。 导入时,只能导入某一个类的这个隐式转换方法=>a对象只能转为某一个类型的对象。

    1. 隐式转换和隐式参数官方概念

    1.1 隐式转换

    Scala提供的隐式转换和隐式参数功能,是非常有特色的功能。是Java等编程语言所没有的功能。它可以允许你手动指定,将某种类型的对象转换成其他类型的对象或者是给一个类增加方法。通过这些功能,可以实现非常强大、特殊的功能。Scala的隐式转换,其实最核心的就是定义隐式转换方法,即implicit conversion function。定义的隐式转换方法,只要在编写的程序内引入,就会被Scala自动使用。Scala会根据隐式转换方法的签名,在程序中使用到隐式转换方法接收的参数类型定义的对象时,会自动将其传入隐式转换方法,转换为另外一种类型的对象并返回。这就是“隐式转换”。其中所有的隐式值和隐式方法必须放到object中。然而使用Scala的隐式转换是有一定的限制的,总结如下: implicit关键字只能用来修饰方法、变量(参数)。隐式转换的方法在当前范围内才有效。如果隐式转换不在当前范围内定义(比如定义在另一个类中或包含在某个对象中),那么必须通过import语句将其导。

    1.2 隐式参数

    所谓的隐式参数,指的是在函数或者方法中,定义一个用implicit修饰的参数,此时Scala会尝试找到一个指定类型的,用implicit修饰的参数,即隐式值,并注入参数。

    Scala会在两个范围内查找:

    当前作用域内可见的val或var定义的隐式变量;一种是隐式参数类型的伴生对象内的隐式值。

    1.3 隐式转换方法作用域与导入

    Scala默认会使用两种隐式转换,一种是源类型,或者目标类型的伴生对象内的隐式转换方法;一种是当前程序作用域内的可以用唯一标识符表示的隐式转换方法。如果隐式转换方法不在上述两种情况下的话,那么就必须手动使用import语法引入某个包下的隐式转换方法,比如*import test._。通常建议,仅仅在需要进行隐式转换的地方,用import导入隐式转换方法,这样可以缩小隐式转换方法的作用域,避免不需要的隐式转换。

    1.4 隐式转换的时机

    当对象调用类中不存在的方法或者成员是,编译器会自动将对象进行隐式转换。当方法中的参数的类型与目标类型不一致时。

    2. 隐式转换和隐式参数案例

    2.1 让File类具备RichFile类中的read方法

    import java.io.File import scala.io.Source /** * 让File类具有read()方法 */ //隐式转换方法的对象 object FileToReadMethod { implicit def fileToNewFile(f: File) = { new NewFile(f) } } //定义一个类, file作为构造参数, class NewFile(val f: File) { //定义一个方法, 读取文件 def read(): String = { Source.fromFile(f).mkString } } //测试object object TestFile { def main(args: Array[String]): Unit = { val file: File = new File("E:\\01HM\\01_pro_spark\\scala-day02\\aaa\\wordCount2.txt") import FileToReadMethod.fileToNewFile val read: String = file.read() println(read) } }

    2.2 超人变身(让Man类具有SuperMan类的方法)

    import day03.implicitDemo.Man /** * 让Man类具有多个超级Man类的方法 */ class Man(val name: String) { } class SuperMan(val name: String) { def heat = { println(name + "超人打怪兽") } } class SuperMan2(val name: String) { def change72 = { println(name + "超人能够72变") } } //隐式转换 object MyImplicit { implicit def manToSuperMan(man:Man) = { new SuperMan(man.name) } implicit def manToSuperMan2(man:Man) = { new SuperMan2(man.name) } } //测试 object MyImplicitTest{ def main(args: Array[String]): Unit = { val man: Man = new Man("蜘蛛侠") import MyImplicit.manToSuperMan man.heat import MyImplicit.manToSuperMan2 man.change72 } }

    2.3 让一个类具有多个类的同一个相同的方法

    import day03r.ImplicitTest /** * */ class C(val name: String) { } class A(val name: String) { def readBook() = { println(name + "说: 好书好书...") } } class B(val name: String) { def readBook() = { println(name + "说: 看不懂...") } def writeBook() = { println(name + "说: 不会写") } } //隐式转换 object MyImplicit2 { implicit def cToA(c:C) = { new A(c.name) } implicit def cToB(c:C) = { new B(c.name) } } //测试 object C { def main(args: Array[String]): Unit = { val c: C = new C("小红") // import MyImplicit2.cToA 不能同时调用不同类的同一个相同方法 import MyImplicit2.cToB c.readBook() c.writeBook() } }

    2.4 隐式参数

    object Company{ //在object中定义隐式值 注意:同一类型的隐式值只允许出现一次,否则会报错 implicit val aaa="zhangsan" implicit val bbb=10000.00 } class Boss { //注意参数匹配的类型 它需要的是String类型的隐式值 def callName()(implicit name:String):String={ name+" is coming !" } //定义一个用implicit修饰的参数 //注意参数匹配的类型 它需要的是Double类型的隐式值 def getMoney()(implicit money:Double):String={ " 当月薪水:"+money } } object Boss extends App{ //使用import导入定义好的隐式值,注意:必须先加载否则会报错 import Company._ val boss =new Boss println(boss.callName()+boss.getMoney()) }
    最新回复(0)