scala----方法与函数 柯里化和隐式参数 RichFile案例 Ordering和Ordered 视图和上下文界定 柯里化结合隐式

方法与函数

将方法生成一个新的函数

package cn.doit.com.day05.demo01

object MethodGenFunc {

  def m(x: Int): Int = x*x

  val f = (a: Int) => a * a

  def main(args: Array[String]): Unit = {

    val r1 = m(5)
    val r2 = f.apply(5)

   val arr = Array(1,2,3,4,5,6,7,8,9)

    //传入函数 生成一个新的arr
    val arr1: Array[Int] = arr.map(f)

    //map方法中只能传入函数 这是一个语法糖,省略了_
    //会生成一个新的函数,调用了原来的方法,逻辑相同
//    val arr2: Array[Int] = arr.map(m)
    val arr2: Array[Int] = arr.map(m _) //真正写法 m后面有个空格
    println(arr2.toBuffer)

  }
}

柯里化和隐式参数

package cn.doit.com.day05.demo2

object KeliDemo {

  def m1(x:Int)(y:Int): Int = x + y

//  def m2(x:Int , y:Int): Int = x + y
  //普通方法可以在参数列表中指定默认值,一般是最后以后参数
  //也可以每个参数都传默认值
    def m2(x:Int , y:Int = 100): Int = x + y
    def m3(x:Int = 100 , y:Int = 50): Int = x + y

  //柯里化
    def m4(x:Int)(y:Int = 100): Int = x + y
    def m5(x:Int = 5)(y:Int = 100): Int = x + y

  //隐式参数implicit 一般情况下是放在后面的参数里
    def m6(x:Int)(implicit y:Int = 100): Int = x + y

      //不是柯里化方法,但是有隐式参数,不一定只有柯里化方法中使用
      def m7(implicit x:Int = 100): Int = x + 55




  def main(args: Array[String]): Unit = {

    // 105
//  val r = m2(5)
    //205 覆盖了默认值
    val r = m2(5,200)

    //覆盖了第一个参数
    val a = m3(5)

    /*
        柯里化方法后面的括号传入的默认值,调用时也要指定多个括号,
        有默认值的括号可以不传参数
     */
    // 没传参使用默认值,()不能少
    val b = m4(5)()
    println(b)
//    val b = m4(5)   //编译时不报错 运行时报错 加了implicit就好了
    //保证对应的个数就可以
    val c = m5()()
    println(c)


    //如果隐式参数 方法定义在class中,先要创建这个类的实例,在用实例名称调用
//    val clazz = new MyContextClass
//    import clazz._

    //将MyContext导进来
    import MyContextObj.im //这是object中的,推荐使用

//    implicit val abc = 661
    //如果上下文中有多个参数类型一样的,编译器会不知道想要传入哪个儿报错
//    implicit val abcd = 666
    //隐式参数: 编译时会去程序的上下文找与自己类型一样,不在乎参数名是否相同,有就传入,覆盖默认值
    val d = m6(5) //加了隐式参数传一个参数就不会报错
//    val e = m6(5)(33) //手动传的优先级最高
    println(d)
    //会去m6的上文去找,在下面不会覆盖
//    implicit val bcd = 777

    val noKeli = m7
    println(noKeli)
  }
}
package cn.doit.com.day05.demo2

object MyContextObj {

  implicit val im = 123456
}

class MyContextClass {
  implicit val ip = 654321
}

RichFile案例

package cn.doit.com.day05.demo3

import scala.runtime.RichInt

object ToDemo {
  def main(args: Array[String]): Unit = {

    //Int 没有定义to方法,父类也没定义
    //使用了隐式转化,使用RichInt中的To方法
    1 to 10
    //不使用隐式转换,显示的包装,要多敲好多次键盘
    val r: Range.Inclusive = new RichInt(1) to (10)

    //隐式转换, 隐式转换本质就是装饰(包装),背地里帮你包的
    //scala默认就导入一些包 类 object. 隐式参数 方法 函数
//    1) import java.lang._             (117 types, 123 terms)
//    2) import scala._                 (178 types, 172 terms)
//    3) import scala.Predef._          (123 terms, 62 are implicit)
    //在 scala.LowPriorityImplicits 中有一个用import修饰的方法
    //implicit def intWrapper(x:Int)  =new runtime.RichInt(x)
    //将Int 转成了 RichInt, 而RichInt中恰好定义了to方法

  }
}
package cn.doit.com.day05.demo3

import java.io.File
import scala.io.Source

class RichFile(val file: File) {

  def read(): String = {
    //从文件中一次全部读取出来
    Source.fromFile(file).mkString
  }
}

object RichFile {
  def main(args: Array[String]): Unit = {

    val file = new File("D:\\a.txt")
//    val content = file.read()

//    val richFile = new RichFile(file)
//    val content = richFile.read()

    import MyPreDef._
    val content = file.read()
    println(content)
  }
}
package cn.doit.com.day05.demo3

import java.io.File

object MyPreDef {

  //隐式方法
  implicit def fileToRichFile(file:File) = {
    println("implicit method invoked")
    new RichFile(file)
  }

  //隐式函数 隐式转换优先调用函数
  implicit val file2RichFile = (file: File) => {
    println("implicit func invoked")
    new RichFile(file)
  }
}

scala的泛型

package cn.doit.com.day05.demo04
/*
* [T <: Comparable[T]] 上界 upper bound     java: <T extends Comparable>
* [T >: Comparable[T]] 下界 lower bound     java: <T super Comparable>
* [T <% Comparable] 视图界定 view  bound     java: <T super Comparable>
* [T : Comparable] 上下文界定 context bound
* [-T] 逆变  方法输入参数
* [+T] 协变  方法返回
* */
class Pair[T <% Comparable[T]] {

  def bigger(first:T, second: T): T ={

    if (first.compareTo(second) > 0) first else second
  }
}


object Pair {
  def main(args: Array[String]): Unit = {

    //Integer实现了Comparable接口
//        val p = new Pair[Integer]
//        val r = p.bigger(5, 10)
//        println(r)

    //如果使用T <% Comparable[T] 即视图界定,既不会报错,因为视图界定就是为了实现隐式转换的
    //在Predef中有一个隐式转换方法 implicit def int2Integer(x: Int): java.lang.Integer = x.asInstanceOf[java.lang.Character]
    val p2 = new Pair[Int]
    //用implicit修饰的一个方法或函数 Int => Integer
    //Int => Integer
    val r2 = p2.bigger(5,10)
    println(r2)
  }
}

Ordering和Ordered 比较

Ordered 是对java 中comparable的一个扩展 , 又更加灵活的方法

Ordering 继承了compaartor 对compare方法进行了扩展

视图界定

<% 视图界定( view bound) 必须传一个隐式方法或函数

​ 视图界定就是为了实现隐式转换 , 寻找对应的隐式转换方法

package cn.doit.com.day05.demo05

//Ordered中有 > < <= >= 等方法
//结论: 视图界定就是用来实现隐式转换的,需要一个隐式转换方法或函数
class MrRight[T <% Ordered[T]] {

  def fanpaizi(first:T,second:T): T = {

    if (first > second) first else second
  }
}

object MrRight {

  def main(args: Array[String]): Unit = {

    import MyPreDef._
    val mr = new MrRight[Boy]

    val b1 = new Boy("zss",99)
    val b2 = new Boy("lss",98)

    val boy = mr.fanpaizi(b1, b2)
    println(boy)
  }
}
package cn.doit.com.day05.demo05

class Boy(val name:String, val fv:Int) /*extends Ordered[Boy]*/{
  override def toString: String = s"Boy($name, $fv)"

  /*override def compare(that: Boy): Int = {
    this.fv - that.fv
  }
*/
}
package cn.doit.com.day05.demo05

object MyPreDef {

 //方法
  implicit def boyToOrderedBoy(boy: Boy): Ordered[Boy] = new Ordered[Boy] {
    override def compare(that: Boy): Int = {
      println("implicit method invoked")
      boy.fv - that.fv
    }
  }

//函数  函数优先级高
  implicit val boy2ToOrderedBoy = (boy: Boy) => new Ordered[Boy] {
    override def compare(that: Boy): Int = {
      println("implicit func invoked")
      boy.fv - that.fv
    }
  }
}

上下文界定

   :   必须传一个隐式类型的参数

package cn.doit.com.day05.demo05

//上下文界定也是用来实现隐式转换的,但是必须有一个隐式转换的类型参数
class MissRight[T : Ordering] {

  def choose(first:T , second:T):T = {
    //把 T:Ordering 转化成了 Ordering[T]类型的
    val ord: Ordering[T] = implicitly[Ordering[T]]
    // gteq: x - y >= 0
    if (ord.gteq(first,second)) first else second
  }
}

object MissRight {

  def main(args: Array[String]): Unit = {

    import MyPreDef.OrderingGirl
    val missr: MissRight[Girl] = new MissRight[Girl]
    val g1 = new Girl("金莲",38)
    val g2 = new Girl("吉泽老师",40)

    val girl = missr.choose(g1, g2)
    println(girl)
  }
}
package cn.doit.com.day05.demo05

class Girl(val name:String , val fv:Double) {

  //重写toString
  override def toString = s"Girl($name, $fv)"
}
package cn.doit.com.day05.demo05

object MyPreDef {
  //既不是方法也不是函数,是一个隐式的object
  implicit object OrderingGirl extends Ordering[Girl] {
    override def compare(x: Girl, y: Girl): Int = {
      //Double实现了comparable接口
      java.lang.Double.compare(x.fv , y.fv)
    }
  }
}

柯里化结合隐式

使用柯里化+隐式转换方法/函数 实现类似视图界定

使用柯里化+隐式参数 实现上下文界定

package cn.doit.com.day05.demo06

import cn.doit.com.day05.demo05.{Girl, MissRight, MyPreDef}

class Pair[T] {

  //柯里化方法结合隐式转换方法或者函数 可以实现数图界定的功能
  def select(first:T , second:T)(implicit f:T => Ordered[T]) = {
    if(first > second) first else second
  }

  //柯里化方法结合隐式类型参数 可以实现上下文界定的功能
  def choose(first:T , second:T)(implicit ord: Ordering[T]): T = {
    if (ord.gteq(first,second)) first else second
  }
}


object Pair {
  def main(args: Array[String]): Unit = {

    val pair = new Pair[Boy]

    val a1 = new Boy("zss",18)
    val a2 = new Boy("lss",28)

    //使用柯里化+隐式转换方法或函数就可以实现类似视图界定的功能
    import MyPreDef._
    val boy = pair.select(a1, a2)
    println(boy)


    val pair2: Pair[Girl] = new Pair[Girl]
    val g1 = new Girl("金莲",38)
    val g2 = new Girl("吉泽老师",40)

    import MyPreDef.OrderingGirl
    val girl = pair2.choose(g1,g2)
    println(girl)
  }
}

package cn.doit.com.day05.demo06

import cn.doit.com.day05.demo05.Girl

object MyPreDef {

  implicit def boyToOrderedBoy(boy: Boy): Ordered[Boy] = new Ordered[Boy] {
    override def compare(that: Boy): Int = {
      println("implicit method invoked")
      boy.fv - that.fv
    }
  }

  implicit val boy2ToOrderedBoy = (boy: Boy) => new Ordered[Boy] {
    override def compare(that: Boy): Int = {
      println("implicit func invoked")
      boy.fv - that.fv
    }
  }

  //既不是方法也不是函数,是一个隐式的object
  implicit object OrderingGirl extends Ordering[Girl] {
    override def compare(x: Girl, y: Girl): Int = {
      //Double实现了comparable接口
      java.lang.Double.compare(x.fv , y.fv)
    }
  }
}
package cn.doit.com.day05.demo06

class Boy(val name:String, val fv:Int){
  override def toString: String = s"Boy($name, $fv)"

}

隐式转换就是想要对方法进行增强,对类进行增强或者扩展, 有两种方式

​ 第一种是 对类进行包装,使用柯里化方法和隐式函数/方法来其进行增强 相当于视图界定

​ 第二种 就是继承, 定义一个隐式的object继承某个类型也可以对其进行增强 相当于上下文界定

在java中扩展方法 :

​ 1. 继承 继承后可以在子类中加方法,可以也重写方法来增强方法

​ 2. 包装

​ 3. 动态代理

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值