乐趣区

关于scala:六Scala隐式转换和泛型

1. 隐式转换

1.1 什么是隐式转换?

看如下示例

object Scala_Transform {def main(args: Array[String]): Unit = {
    val byte_num:Byte = 21
    val int_num:Int = byte_num
    println(int_num)
  }
}

这个可能失常打印,因为可能编译器可能进行主动转换,但如果代码改货色,由 int 转换成 byte

object Scala_Transform {def main(args: Array[String]): Unit = {
    val int_num:Int = 21
    val byte_num:Byte = int_num // 这里会出错
    println(byte_num)
  }
}

出错起因由 Int 到 Byte 没有间接的关系,编译器找不到对应的转换方法。
那么咱们提供一个

object Scala_Transform {def main(args: Array[String]): Unit = {
    // int 转换成 byte 的办法
    def itbFun(x:Int):Byte = {x.toByte}

    val int_num:Int = 21
    val byte_num:Byte = itbFun(int_num)// 这里会出错
    println(byte_num)
  }
}

然而这样又批改了代码逻辑,那么是否让编译器本人找到转换方法来进行转换呢?这时候只有在办法前加上一个关键字 implicit

object Scala_Transform {def main(args: Array[String]): Unit = {
    // int 转换成 byte 的办法
    implicit def itbFun(x:Int):Byte = {x.toByte}

    val int_num:Int = 21
    val byte_num:Byte = int_num
    println(byte_num)
  }
}

编译就会主动找到转换的办法,来进行转换,这个就是隐式转换。

1.2 隐式办法

在函数申明前减少 implicit 关键字,编译器就能自动识别和主动调用实现类型的转换,这样的办法就叫隐式办法。

object Scala_Transform {def main(args: Array[String]): Unit = {
    val person = new Person
    person.info()
    
    // 因为需要变动,咱们须要在原有信息打印根底上加上性别地址 address 信息
    // 咱们能够应用隐式办法来实现这个
    implicit def transformFun(person: Person): PersonInfoAdd ={new PersonInfoAdd}
    person.updateInfo()}
  
  class Person {def info(): Unit ={println("name:xxx age:xxx")
    }
  }
  
  // 扩大类
  class PersonInfoAdd{def updateInfo():Unit = {println("address:xxxx")
    }
  }
  
}

在应用时须要留神,以后范畴内,雷同的转换规则只能有一个。
隐式转换方法会在第一次编译出错时,抉择隐式转换,所以也叫二次编译。

1.3 隐士参数和隐士变量

implicit 除了润饰办法外,还能够润饰参数,这个就是隐式参数。
当咱们事后晓得办法的参数会发生变化时,咱们能够应用 implicit 要害来润饰的这个参数。
隐士变量,就是编译器主动找到并传递的参数值
示例

object Scala_Transform {def main(args: Array[String]): Unit = {
    // 登录账号,最开始应用默认明码 123456 登录,前期应用用户自定义的明码登录
    def loginFun(user:String)(implicit pwd:String="123456"): Unit ={println(s"用户:$user, 明码:$pwd")
    }

    // 隐士变量
    implicit val pwd:String = "123123"

    // 应用隐士参数时,前面省略小括号
    loginFun("user1") // 输入后果  用户:user1, 明码:123123

    // 不省略小括号,会传递默认值或者自定义参数,而不应用隐式变量
    loginFun("user1")() // 输入后果 用户:user1, 明码:123456
    loginFun("user1")("666666") // 输入后果 用户:user1, 明码:666666
  }
}

1.4 隐士类

隐式类是 2.10 版本减少的
示例

object Scala_Transform {def main(args: Array[String]): Unit = {
    val person = new Person
    person.info()

    person.updateInfo()
   // 隐士类的查找程序
   // 1)第一个是以后作用域
   // 2)下级作用域
   // 3)以后类所在的包对象
   // 4)父类
   // 5)特质
   
   // 个别咱们应用隐士类转换时,能够间接导入
   
  }

  class Person {def info(): Unit ={println("name:xxx age:xxx")
    }
  }

  // 隐式类
  // implicit 润饰,结构参数要存在且只有一个,用于类型转换
  implicit class PersonInfoAdd(person: Person){def updateInfo():Unit = {println("address:xxxx")
    }
  }

}

2. 泛型

2.1 Scala 泛型

泛型用于指定办法或类能够承受任意类型参数,参数在理论应用时才被确定,泛型能够无效地加强程序的适用性,应用泛型能够使得类或办法具备更强的通用性。
Scala 中泛型和 Java 泛型统一,但性能更加弱小,申明时应用[]

2.2 泛型类、泛型办法

泛型类:指定类能够承受任意类型参数。
泛型办法:指定办法能够承受任意类型参数。

示例

object Scala_Generic {def main(args: Array[String]): Unit = { }
  // 应用 [] 申明泛型
  class DemoClass[T] {private val list:List[T] = Nil
  }

}

2.3 泛型转换

2.3.1 泛型不可变

示例

object Scala_Generic {def main(args: Array[String]): Unit = {
    // 泛型不可变
    val demo1:Demo[Student] = new Demo[Student] // 正确
    val demo2:Demo[Student] = new Demo[Person] // 谬误
    val demo3:Demo[Student] = new Demo[Student_Of_BJ] // 谬误
    
    // 从后果上看,在咱们惯例申明,没有采纳其余路径时,泛型是不可变的

  }
  class Demo[T] { }

  class Person{ }

  class Student extends Person{ }

  class Student_Of_BJ extends Student{}}

2.3.2 泛型协变

Scala 能够让下面代码 “val demo3:Demo[Student] = new Demo[Student_Of_BJ]” 可能通过的,也就是说,泛型能够将子类型当成父类型应用,这个是泛型的协变
示例代码

object Scala_Generic {def main(args: Array[String]): Unit = {
    // 泛型协变
    val demo1:Demo[Student] = new Demo[Student] // 正确
    val demo2:Demo[Student] = new Demo[Person] // 谬误
    val demo3:Demo[Student] = new Demo[Student_Of_BJ] // 正确

  }
  // 非常简单,只有在泛型前用 "+"
  class Demo[+T] { }

  class Person{ }

  class Student extends Person{ }

  class Student_Of_BJ extends Student{}}

2.3.4 泛型逆变

泛型能够将父类型当成子类型应用,应用[-T] 申明泛型

object Scala_Generic {def main(args: Array[String]): Unit = {
    // 泛型逆变
    val demo1:Demo[Student] = new Demo[Student] // 正确
    val demo2:Demo[Student] = new Demo[Person] // 正确
    val demo3:Demo[Student] = new Demo[Student_Of_BJ] // 谬误
    
  }
  // 加个减号即可
  class Demo[-T] { }

  class Person{ }

  class Student extends Person{ }

  class Student_Of_BJ extends Student{}}

2.3.5 泛型的下限与上限

在指定泛型类型时,有时须要界定泛型类型的范畴,而不是接管任意类型。
Scala 的高低边界个性容许泛型类型是某个类的子类,或者是某个类的父类;
(1) U >: T
这是类型下界的定义,也就是 U 必须是类型 T 的父类 (或自身,本人也能够认为是本人的父类)。
(2) S <: T
这是类型上界的定义,也就是 S 必须是类型 T 的子类(或自身,本人也能够认为是本人的子类)。

示例

object Scala_Generic {def main(args: Array[String]): Unit = { }
  class Person{ }

  class Student extends Person{ }

  class Student_Of_BJ extends Student{ }
  
  class Demo{
    // 泛型下限
    def fun1[T<:Student](t:T)= {}
    // 泛型上限
    def fun2[T>:Student](t:T)= {}}

}
退出移动版