Scala函数式编程高级

偏函数

偏函数,就是 PartialFunction 特质的匿名对象
isDefinedAt 方法 接收的any ,返回一个布尔, 业务逻辑有程序员编写
apply 表示如果 对于某个元素进行isDefinedAt  处理,返回true就调用 apply ,否则,就不处理该元素
使用偏函数,使用 collect

    val addOne3= new PartialFunction[Any, Int] {
      def isDefinedAt(any: Any) = {
        println("isDefinedAt 被调用" + any)
        if (any.isInstanceOf[Int]) true else false
      }
      def apply(any: Any) = {
        println("apply 被调用" + any)
        any.asInstanceOf[Int] + 1
      }
    }

    println(list6.collect(addOne3))
    //简化形式
    val list31 = List(1, 2, 3, 4,"ABC").collect{ case i: Int => i + 1 }

闭包

def minusxy(x: Int) = (y: Int) => x – y

minusxy(20)(10)

返回的是一个匿名函数 ,因为该函数引用到到函数外的 x,那么  该函数和x整体形成一个闭包

例如需求:

请编写一个程序,具体要求如下

  • 编写一个函数 makeSuffix(suffix: String)  可以接收一个文件后缀名(比如.jpg),并返回一个闭包
  • 调用闭包,可以传入一个文件名,如果该文件名没有指定的后缀(比如.jpg) ,则返回 文件名.jpg , 如果已经有.jpg后缀,则返回原文件名。
  • 要求使用闭包的方式完成

def makeSuffix(suffix: String) = { //接受字符串
(name: String) => {  //传入一个文件名[可能有后缀,可能没有]
if (name.endsWith(suffix)) name // 如果有,返回原文件名
else name + suffix //如果没有就,拼接该后缀名
}}

我们体会一下闭包的好处,如果使用传统的方法,也可以轻松实现这个功能,但是传统方法需要每次都传入 后缀名,比如 .jpg ,而闭包因为可以保留上次引用的某个值,所以我们传入一次就可以反复使用。大家可以仔细的体会一把!

函数柯里化

  • 函数编程中,接受多个参数的函数都可以转化为接受单个参数的函数,这个转化过程就叫柯里化

def mulCurry2(x: Int)(y:Int) = x * y
println(mulCurry2(10)(8))

scala枚举


object SeasonEm extends Enumeration {
      type SeasonEm = Value
      val spring, summer, winter, autumn = Value
    }
    SeasonEm.spring

scala泛型上下界


//上界
class CompareComm[T <: Comparable[T]](obj1: T, obj2: T) {
  def greater = if(obj1.compareTo(obj2) > 0) obj1 else obj2
}
  1. 对于下界,可以传入任意类型
  2. 传入和Animal直系的,是Animal父类的还是父类处理,是Animal子类的按照Animal处理(编译类型), 仍然遵守 动态绑定机制
  3. 和Animal无关的,一律按照Object处理[编译类型], 遵守动态绑定机制
  4. 也就是下界,可以随便传,只是处理是方式不一样
  5. 不能使用上界的思路来类推下界的含

package com.gdj

/**
 * @author gdj
 * @create 2020-01-06-21:27
 *
 */

object TText {

  def main(args: Array[String]): Unit = {
    biophony(Seq(new Earth, new Earth)).map(_.sound()) //ok hello !, hello !
    biophony(Seq(new Animal, new Animal)).map(_.sound()) // ok animal sound animal sound
    biophony(Seq(new Bird, new Bird)).map(_.sound())
    biophony(Seq(new Moon))

    //结论在笔记
    //    def biophony[T >: Animal](things: Seq[T]) = things
    //
    //    1)对于下界,可以传入任意类型
    //    2)传入和Animal直系的,是Animal父类的还是父类处理,是Animal子类的按照Animal处理(编译类型), 仍然遵守 动态绑定机制
    //      3)和Animal无关的,一律按照Object处理[编译类型], 遵守动态绑定机制
    //    4)也就是下界,可以随便传,只是处理是方式不一样
    //    5)不能使用上界的思路来类推下界的含义
    // 因为 T >: Animal ,因此 编译器认为不是所有的 Animal都有sound ,因此报错
    def biophony[T >: Animal](things: Seq[T]) = things
  }

  class Earth { //Earth 类
    def sound() { //方法
      println("hello !")
    }

    def say(): Unit = {
    }
  }

  class Animal extends Earth {
    override def sound() = { //重写了Earth的方法sound()
      println("animal sound")
    }
  }

  class Bird extends Animal {
    override def sound() = { //将Animal的方法重写
      print("bird sounds")
    }
  }

  class Moon {
    def hello(): Unit = {
    }
  }

}

类型约束-视图界定

它比<:适用的范围更广,除了所有的子类型,还允许隐式转换类型


    val compareComm1 = new CompareComm(20, 30)
    println(compareComm1.greater)
  class CompareComm[T &lt;% Comparable[T]](obj1: T, obj2: T) {
    def greater = if(obj1.compareTo(obj2) > 0) obj1 else obj2
  }

协变逆变


C[+T]:如果A是B的子类,那么C[A]是C[B]的子类,称为协变
C[-T]:如果A是B的子类,那么C[B]是C[A]的子类,称为逆变
C[T]:无论A和B是什么关系,C[A]和C[B]没有从属关系。称为不变.
Scala函数式编程高级

发表评论

电子邮件地址不会被公开。 必填项已用*标注

滚动到顶部