隐式转换
作用:能够丰富现有类库的功能,对类的方法进行增强
隐式转换函数
以implicit关键字声明并带有单个参数的函数
比如1 to 10其实是调用的1.to(10)这个方法
但是在Int类中并没有to这个方法
int 的to方法实际上是调用RichInt里的intWrapper方法,最终调用的是RichInt里的to方法
intWrapper就是以implicit关键字声明并带有单个参数的函数,intWrapper就是一个隐式转换函数
predef这个类就是预定义的predefine的简写
在shell中用:implicit -v来查看,默认有多少个隐式转换函数
在2.11.8中有69个隐式转换,scala升级比较快所以其它版本可能不同
隐式转换函数其实用到了装饰模式
装饰模式对应的是门面模式
隐式转换练习:
给代表文件地址的字符串增加一个可以读文件的功能
import scala.io.Source
class ImplicitFunctionDemo(val path:String) {
def read():String = {
Source.fromFile(path).mkString
}
}
object ImplicitFunctionDemo{
def main(args: Array[String]): Unit = {
val path = "C:\\Users\\Leo.He\\Desktop\\抽取项目描述.txt"
val content: String = new ImplicitFunctionDemo(path).read()
println(content)
}
}
这是一个显示的调用并不是一个隐式的调用,这是我们平时开发过程中常用的方法
隐式转换函数的实现方法
1.首先在MyPredef写一个String的隐式转换函数
object MyPredef {
implicit def pathStringToImplicitFunction(path:String) = new ImplicitFunctionDemo(path)
}
2.然后修改刚才的类为隐式转换的调用方式,在使用隐式转换中String类型的path变量就有了read方法,这个read实现上是ImplicitFunctionDemo的read。
这个转换过程是由MyPredef里的隐式转换函数完成的
import scala.io.Source
class ImplicitFunctionDemo(val path:String) {
def read():String = {
Source.fromFile(path).mkString
}
}
object ImplicitFunctionDemo{
def main(args: Array[String]): Unit = {
val path = "C:\\Users\\Leo.He\\Desktop\\抽取项目描述.txt"
val content: String = new ImplicitFunctionDemo(path).read()
println(content)
import MyPredef.pathStringToImplicitFunction
val content1 = path.read()
println(content1)
}
}
隐式转换与柯里化的使用
shell中柯里化与隐式转换使用的例子
/**
* 这里用到了隐式转换、隐式值、柯里化(隐式参数)、内部类、泛型、特质、比较的方法、重写toString方法
* 首先import OrderingDemo.OrderStudent
* OrderStudent是Ordering[HainiuStudent]的子类
* 所以demo.comp() 柯里化方法(def comp()(implicit ord:Ordering[HainiuStudent])) 第二个参数会匹配到OrderStudent
* 所以ord的值传入的是OrderStudent
* ord.gt(v1,v2)调用的是OrderStudent的gt方法也就是ordering的gt方法(def gt(x: T, y: T): Boolean = compare(x, y) > 0)
* ordering的gt方法中调用的是compare,但OrderStudent是ordering的子类实现,所以调用的是orderStudent的compare方法
* 由OrderStudent的compare方法返回会的正负值决定了返回true还是false,(Boolean = compare(x, y) > 0) 大于0是true小于0是false
* demo.comp()(def comp()(implicit ord:Ordering[T]))方法返回比较之后的对象
* println(student)打印了对象重写的toString方法(override def toString: String = s"name:$name,age:$age")的返回值
*/
object OrderingDemo {
implicit object OrderStudent extends Ordering[HainiuStudent]{
override def compare(x: HainiuStudent, y: HainiuStudent): Int = if(x.age > y.age) 1 else -1
}
}
class CompareDemo[T:Ordering](val v1:T,val v2:T){
def comp()(implicit ord:Ordering[T]) = if(ord.gt(v1,v2)) v1 else v2
}
object CompareDemo{
def main(args: Array[String]): Unit = {
import OrderingDemo.OrderStudent
val s1 = new HainiuStudent("牛1",24)
val s2 = new HainiuStudent("牛2",23)
val demo = new CompareDemo[HainiuStudent](s1,s2)
// val demo = new CompareDemo(s1,s2) //简写的方式
val student: HainiuStudent = demo.comp()
println(student)
}
}
class HainiuStudent(val name:String,val age:Int){
override def toString: String = s"name:$name,age:$age"
}
泛型:
泛型就是不确定的类型,可以在类或方法不确实传入类型时使用,可以提高代码的灵活性和复用性
scala中泛型的用法和java中差不多,但是会有一些自己独特的语法
比如说ordering中泛型的一些特殊符号
这个叫ViewBound
这个叫UpperBound
泛型:
[B <: A] UpperBound 上界,B类型的父类是A类型
[B >: A] LowerBound 下界,B类型的子类是A类型
[B <% A] ViewBound B类型转换成A类型,需要一个隐式转换函数
[B : A] ContextBound 需要转换成A[B]类型,需要一个隐式转换的类型
[-A] 逆变,作为参数类型,T是A的子类
[+B] 协变,作为返回类型,T是B的父类
UpperBound
class UpperBoundDemo[T <: Comparable[T]] {
def choose(a:T,b:T):T = {
if(a.compareTo(b) > 0) a else b
}
}
object UpperBoundDemo{
def main(args: Array[String]): Unit = {
val u = new UpperBoundDemo[HaniuEngineer]
val h1 = new HaniuEngineer("牛大",20)
val h2 = new HaniuEngineer("牛二",22)
println(u.choose(h1,h2))
}
}
class HaniuEngineer(val name:String,val age:Int) extends Comparable[HaniuEngineer]{
override def compareTo(o: HaniuEngineer): Int = {
this.age - o.age //SCALA中访问本类的属性也可以用this
}
override def toString: String = {
s"${name}我年纪大"
}
}
ViewBound
class ViewBoundDemo[T <% Ordered[T]] {
def choose(work1:T,work2:T):T={
if(work1 > work2) work1 else work2
}
}
object ViewBoundDemo{
def main(args: Array[String]): Unit = {
import MyPredef.selectWork
val demo = new ViewBoundDemo[HainiuWork]
val work1 = new HainiuWork("金融",20000,10)
val work2 = new HainiuWork("互联网",20000,6)
print(demo.choose(work1,work2))
}
}
class HainiuWork(val company:String,val money:Int,val holiday:Int){
override def toString: String = {
s"go to $company,happy holiday $holiday"
}
}
隐式转换函数实现
版权声明:原创作品,允许转载,转载时务必以超链接的形式表明出处和作者信息。否则将追究法律责任。来自海汼部落-青牛,http://hainiubl.com/topics/210