scala-柯里化、隐式转换、泛型、
upperbound、viewbound、contextBound
一、柯里化
1.1 定义:
在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术。这个技术由 Christopher Strachey 以逻辑学家 Haskell Curry 命名的,尽管它是 Moses Schnfinkel 和 Gottlob Frege 发明的。
1.2 简单举例
package day03 class CurryingDemo { } object Contest{ implicit val a = 100 } object CurryingDemo{ //柯里化 def main(args: Array[String]): Unit = { import Contest.a val b = m1(3)(a) val result01 = m1(3) val result02 = m1(3)(4) val result03 = m2(8)(9) println(b) println("result01 : "+result01) println(result02) println(result03) println(ArraySum.sum) } def m1(x:Int)(implicit y:Int = 7) = x * y def m2(x:Int) = (y:Int) =>x * y } //数组后面值进行求和 object ArraySum{ val arr = Array(("array",1),("scala",2),("java",3),("python",4)) val sum = arr.foldLeft(0)(_ + _._2) }
二、隐式转换
定义:我们想要扩展新功能的时候,scala提供了隐式转换机制和隐式参数帮我们解决诸如这样的问题。当Scala编译器进行类型匹配时,如果找不到合适的候选,那么隐式转化提供了另外一种途径来告诉编译器如何将当前的类型转换成预期类型。
简单举例:
package day03 import scala.io.Source /** * 隐式转换举例 * */ class RichIntDemo(val filepath:String) { def read() = { //读取到文件,返回String字符串 Source.fromFile(filepath,"GBK").mkString("") } } object RichIntDemo{ def main(args: Array[String]): Unit = { //1, to 方法是在 RichInt 防范里面 val a = 1 to 10 println(a) //2.1 显示转换:读取文件内容,并打印。 val filepath:String = "C:/Users/Administrator/Desktop/c.txt" val content01 = new RichIntDemo(filepath).read() println("content01"+content01) //2.2 隐式转换: import day03.MyPredef.fileToRichFile val content02 = filepath.read() println("content02"+content02) } }
三、泛型
3.1 简介
- 泛型类、泛型函数
- 泛型用于指定方法或类可以接受任意类型参数
- 参数在实际使用时才被确定
- 泛型可以有效地增强程序的适用性
- 使用泛型可以使得类或方法具有更强的通用性
3.2 七种形式
[A<:] :上边界:表达了泛型的类型必须是"某种类型"或某种类型的"子类"
案例:override def toSet[B >: A]: Set[B] = {}
[A>:] :下边界:表达了泛型的类型必须是"某种类型"或某种类型的"父类"
案例:override def toSet[B >: A]: Set[B] = {}
[A<%] : view bounds可以进行某种神秘的转换,把你的类型在没有知觉的情况下转换成目标类型
可以认为view bounds是上下边界的加强和补充,语法为:"<%",要用到implicit进行隐式转换
“T:classTag”:相当于动态类型,你使用时传入什么类型就是什么类型
逆变和协变:-T和+T: +T可以传入其子类和本身(与继承关系一至)-T可以传入其父类和本身(与继承的关系相反)
案例:trait scala.collection.immutable.Map[K, +V] extends Iterable[(K, V)]
“T:Ordering” :表示将T变成Ordering[T],可以直接用其方法进行比大小,可完成排序等工作
[A]: 一般形式
简单实例进行说明:比较两个动物谁跑的快,speed大的被打印。在第(3)(4)中加了另外一个属性,就是age,age小的获胜被打印出来。
(1)实际使用协变实现
package day03 /** * 练习技术,隐式转换、隐式值、柯里化、泛型、内部类 * 练习内容,比较两个动物的速度 * * 实现过程: * 1,定义一个class动物类,构造器中包含动物名称和动物速度两个属性 * 2,定义类,构造器中包含两个比较对象,写一个比较方法,利用的是Ordering方法中的gt方法进行比较。 * 3,Ordering是如何进行比较的呢?继承Ordering特质。重写compare方法,规定,规则。 * * * */ class SpeedEqual { } object ImplicitContext{ implicit object OrderingAnimal extends Ordering[Animal]{ override def compare(x: Animal, y: Animal): Int = if(x.speed > y.speed) 1 else -1 } } class AnimalFirst[T:Ordering](val an1:T,val an2:T){ def choose()(implicit ord:Ordering[T]) = if(ord.gt(an1,an2)) an1 else an2 } class Animal(val name:String,val speed:Int){ // toString方法 override def toString: String = s"name: $name, speed: $speed" } object AnimalEquals{ def main(args: Array[String]): Unit = { import ImplicitContext.OrderingAnimal val dog = new Animal("dog",200) val cat = new Animal("cat",100) val animalFirst = new AnimalFirst(dog,cat) val animal_king = animalFirst.choose() println(animal_king) } }
(2)upperBound
package day03 /** * 泛型 * [B <: A] UpperBound 上界:B类型的上界是A类型。 即 B类型的父类是A类型 * [B >: A] LowerBound 下届:B类型的下界是A类型。 即 B类型的子类是A类型 * [B <% A] ViewBound 表示B类型要转换成A类型,需要一个隐式转换函数 * [B : A] ContextBound 需要一个隐式转换值 * * [-A, +B] * [-A] 逆变,作为参数类型,如果A是B的子类,那么C[B]是C[A]的子类 * [+B] 协变,作为返回类型,如果A是B的子类,那么C[A]是C[B]的子类 * 实现内容,比较谁的速度更快一点: * [B <: A] 表示B是A的子类 * */ //写一个比较的方法,而Comparable有比较的方法。那就可以作文他的子类进行 class SelectAnimal[T <: Comparable[T]]{ def select(first:T,second:T): T ={ if(first.compareTo(second)>0) first else second } } //写一个类,1为了声明属性。2为了继承(特质)Compareable实现其比较类 class Animal002(val name:String,val speed:Int) extends Comparable[Animal002]{ override def compareTo(o: Animal002): Int = { this.speed-o.speed } } object UpperBound{ def main(args: Array[String]): Unit = { val dog = new Animal002("dog",100) val cat = new Animal002("cat",99) val animalCompare = new SelectAnimal[Animal002] val animal_first: Animal002 = animalCompare.select(dog,cat) println(animal_first.name) } }
(3)ViewBound
package day03 object ViewBound { def main(args: Array[String]): Unit = { import day03.MyPredef.selectAnimal2 val dog01 = new Animal003("dog", 6, 188) val cat01 = new Animal003("cat", 5, 188) val view_ani = new ViewBound[Animal003] val animalSelect = view_ani.select(dog01, cat01) println(animalSelect.name) } } //想用viewBound来比较。进行A类型转换成B类型,声明一个viewBound类。注意的是 用[]来进行包裹。 class ViewBound[T <% Ordered[T]] { def select(first: T, second: T): T = { if (first > second) first else second } }
package day03 //隐式转换 object MyPredef { implicit def fileToRichFile(filename:String) = new RichIntDemo(filename) implicit val selectAnimal2 =(an2:Animal003) => new Ordered[Animal003]{ override def compare(that: Animal003): Int = { if(an2.speed == that.speed ){ that.age - an2.age }else{ an2.speed-that.speed } } } }
(4)ContextBound
package day03 // class ContextBound [T:Ordering]{ def select(first:T,second:T): T ={ val ord:Ordering[T] = implicitly[Ordering[T]] if (ord.gt(first,second)) first else second } } object ContextBound{ def main(args: Array[String]): Unit = { val dog01 = new Animal003("dog", 6, 188) val cat01 = new Animal003("cat", 5, 188) import day03.MyPredef.selectAnimal2 val animal = new ContextBound[Animal003] val animalSelect = animal.select(dog01,cat01) println(animalSelect.name) } }
package day03 //隐式转换 object MyPredef { implicit object SelectAnimal extends Ordering[Animal003]{ override def compare(x: Animal003, y: Animal003): Int = if(x.speed - y.speed == 0){ y.age - x.age }else{ x.speed -y.speed } } }