scala 基础 4

教程 青牛 ⋅ 于 2017-11-28 16:29:49 ⋅ 最后回复由 admin123 2020-02-19 16:14:21 ⋅ 9100 阅读

隐式转换

作用:能够丰富现有类库的功能,对类的方法进行增强

隐式转换函数

以implicit关键字声明并带有单个参数的函数

比如1 to 10其实是调用的1.to(10)这个方法
但是在Int类中并没有to这个方法

file

file

file

file

int 的to方法实际上是调用RichInt里的intWrapper方法,最终调用的是RichInt里的to方法
intWrapper就是以implicit关键字声明并带有单个参数的函数,intWrapper就是一个隐式转换函数
predef这个类就是预定义的predefine的简写

file
在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中柯里化与隐式转换使用的例子

file

/**
  * 这里用到了隐式转换、隐式值、柯里化(隐式参数)、内部类、泛型、特质、比较的方法、重写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中泛型的一些特殊符号

file
这个叫ViewBound

file
这个叫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
回复数量: 11
暂无评论~~
  • 请注意单词拼写,以及中英文排版,参考此页
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`, 更多语法请见这里 Markdown 语法
  • 支持表情,可用Emoji的自动补全, 在输入的时候只需要 ":" 就可以自动提示了 :metal: :point_right: 表情列表 :star: :sparkles:
  • 上传图片, 支持拖拽和剪切板黏贴上传, 格式限制 - jpg, png, gif,教程
  • 发布框支持本地存储功能,会在内容变更时保存,「提交」按钮点击时清空
Ctrl+Enter