美文网首页
scala(五) 函数式编程

scala(五) 函数式编程

作者: 万事万物 | 来源:发表于2021-06-22 08:04 被阅读0次
    1. 面向对象编程
      解决问题,分解对象,行为,属性,然后通过对象的关系以及行为的调用来解决问题。
      对象:用户;
      行为:登录、连接jdbc、读取数据库
      属性:用户名、密码
      Scala语言是一个完全面向对象编程语言。万物皆对象
    2. 函数式编程
      解决问题时,将问题分解成一个一个的步骤,将每个步骤进行封装(函数),通过调用这些封装好的步骤,解决问题。
      例如:请求->用户名、密码->连接jdbc->读取数据库
      Scala语言是一个完全函数式编程语言。万物皆函数
    3. 在Scala中函数式编程和面向对象编程融合在一起了。

    方法基本语法

    语法:


    scala语法

    说明:

    1. def : 关键字,表示声明方法
    2. add:方法名,根据业务进行取名
    3. 参数名称在前 : 参数类型在后,多个参数用 , 分割
    4. 返回类型:若无返回类型 可定义为 Unit 或 无需定义
    5. 函数体:用于编写的业务逻辑的语句块

    与java方法的区别:

    1. scala 可以将函数定义到任意位置,甚至在一个函数内定义一个函数。
    def main(args: Array[String]): Unit = {
        def sayHello(){
          print("hello")
        }
        sayHello // hello
    }
    
    1. java 只能将方法定义在类中,不能定义在另一个方法中

    方法的定义:

    1. 函数1:无参,无返回值
      def sayHello(){
          print("hello")
      }
    
    1. 函数2:无产,有返回值
      def main(args: Array[String]): Unit = {
        
        println(sayHello) // hello
      }
    
      def sayHello():String={
          "hello"
      }
    
    1. 函数3:有参,无返回值
      def main(args: Array[String]): Unit = {
        
        sayHello("张三")
      }
    
      def sayHello(name:String){
          println(s"你好,$name 童鞋") // 你好,张三 童鞋
      }
    
    
    1. 函数4:有参,有返回值
      def main(args: Array[String]): Unit = {
        
        println(sum(10,20)) // 30
      }
    
      def sum(x:Int,y:Int):Int={
         x+y
      }
    
    1. 函数5:多参,无返回值
      def main(args: Array[String]): Unit = {
        
        sum(10,20) // 30
      }
    
      def sum(x:Int,y:Int){
         println(x+y) //30
      }
    
    1. 在scala中函数可以不用加 return 用来标识返回值,在scala中会以最后一个参数或表达式的结果作为返回值。

    方法参数

    可变参数
    无论是 scala 还是 java 他们都支持 可变参数
    java :使用 ... 来表示
    scala:使用 * 来表示
    案例:

      def main(args: Array[String]): Unit = {
        info("坤坤","唱","跳","Rap","篮球")
      }
    
      def info(name:String,hobby:String*):Unit={
         println(s"我叫$name,我的爱好有${hobby.toList}") // 我叫坤坤,我的爱好有List(唱, 跳, Rap, 篮球)
      }
    

    可变参数底层实现都是一个数组或集合,所以直接遍历可变参。

     def info(name:String,hobby:String*):Unit={
        for (h <- hobby){
          println(h)
        }
    }
    
    唱
    跳
    Rap
    篮球
    

    使用 可变参数需要注意:

    1. 被定义成可变参数的参数,需要放在参数列表最后。
    2. 一个方法中只能有一个可变参数。
    3. 可变参数不能与带名参数一起使用(后面会讲)

    带参默认值
    在程序开发中,往往有这样的需求,当某些值为null或0时,我们需要判断,然后给它指定一个默认值。
    如:不指定性别,就会使用默认的性别 'M'

      def main(args: Array[String]){
        info("坤坤",60)
      }
    
      def info(name:String,age:Int,sex:Char='M'){
        println(s"姓名:$name,年龄:$age,性别:$sex") // 姓名:坤坤,年龄:60,性别:M
      }
    

    我们手动指定一个性别 'F'

      def main(args: Array[String]){
        info("坤坤",60,'F')
      }
    
      def info(name:String,age:Int,sex:Char='M'){
        println(s"姓名:$name,年龄:$age,性别:$sex") // 姓名:坤坤,年龄:60,性别:F
      }
    

    至于语法:以这样的形式sex:Char='M'定义的参数,就是表示给参数一个默认值。

    常见错误写法:

    • sex='M' :Char:我有时候也不会搞错,直到运行报错才反应过来。
    • sex='M':这种形式的写法也是错误的,必须指定类型。

    带名参数
    以上面的案例说明;第一个参数为姓名,第二个参数为年龄,第三个参数为性别,一般情况下函数调用参数,就按照函数定义时的参数顺序一个个传递。但是我们也可以通过指定函数参数名,并且不需要按照顺序向函数传递参。

    info(age=60,sex='F',name="坤坤")

      def main(args: Array[String]){
        info(age=60,sex='F',name="坤坤")
      }
      def info(name:String,age:Int,sex:Char='M'){
        println(s"姓名:$name,年龄:$age,性别:$sex")
      }
    }
    
    姓名:坤坤,年龄:60,性别:F
    

    方法至简原则(\color{red}{重点}

    1. return 可以省略,scala 会使用函数体的最后一行代码作为返回值
    def main(args: Array[String]): Unit = {
        def say(context:String):String = {
          context
        }
        print(say("hello")) // hello
      }
    
    1. 如果函数体只有一行代码,可以省略花括号
    def main(args: Array[String]): Unit = {
        def say(context:String):String = context
        print(say("hello")) //hello
    }
    
    1. 返回值类型如果能够推断出来,那么可以省略(:和返回值类型一起省略)
    def main(args: Array[String]): Unit = {
        def say(context:String)= context
        print(say("hello")) // hello
    }
    
    1. 如果有 return,则不能省略返回值类型,必须指定。
    def main(args: Array[String]): Unit = {
        def say(context:String):String = return context
        print(say("hello")) //hello
    }
    
    1. 如果函数明确声明 unit,那么即使函数体中使用 return 关键字也不起作用
    def main(args: Array[String]): Unit = {
        def say(context:String):Unit = return context
        print(say("hello")) // ()
    }
    
    1. scala 如果期望时无返回值类型,可以省略等号
    def main(args: Array[String]): Unit = {
        def say(context:String) { print(context)}
        say("hello") // hello
    }
    

    7.如果参数无参,但是声明了参数列表,那么调用时,小括号,可以不加。

    def sayHello{print("hello")}
    sayHello
    
    1. 如果函数没有参数列表,那么小括号可以省略,调用时小括号必须省略
    定义函数:def sayHello{print("hello")}
    掉用函数:必须省略小括号 sayHello
    
    1. 如果不关心名称,只关心逻辑处理,那么函数名称(def)可以省略。这种声明方式叫做 匿名函数(lambda 表达式)。
    ()=>{print("hello")}
    

    总结:虽然很多简化原则,但是不用去记,多敲就完了(我也记不住,没事的时候,回顾一下笔记,知道个大概就行了。


    函数的定义

    语法
    val 函数名 =(参数名:类型,...) => {函数体}

        // 计算两个数的和
        val sum=(x:Int,y:Int)=>{
          x+y
        }
    
        println(sum(2,3)) // 5
    
    1. 并不需要写返回值,函数的返回值就是块表达式最终返回代码结果。
    2. 调用函数和调用方法是一样的。

    函数的简化

    1. return 可以省略,scala 会使用函数体的最后一行代码作为返回值
    val sum=(x:Int,y:Int)=>{
        x+y
    }
    
    1. 如果函数体只有一行代码,可以省略花括号
    // 计算两个数的和
    val sum=(x:Int,y:Int)=> x+y
    println(sum(2,3)) // 5
    
    1. 返回值类型如果能够推断出来,那么可以省略(:和返回值类型一起省略)
    // 计算两个数的和
    val sum=(x:Int,y:Int)=> x+y
    println(sum(2,3)) // 5
    
    1. 如果有 return,则不能省略返回值类型,必须指定。
    函数中无法指定返回值,至少我试了好几次没成功
    
    1. 如果函数明确声明 unit,那么即使函数体中使用 return 关键字也不起作用
    上面的都不行,这个也自然没用了
    
    1. scala 如果期望时无返回值类型,可以省略等号
    没有等号,哈哈哈
    
    1. 如果参数无参,但是声明了参数列表,那么调用时,小括号,可以不加。
        val sayHello=()=>{
          println("hello")
        }
    

    不行,无法调用;函数就是一个对象,sayHello 这是这个函数的引用,并不是调用。

    sayHello 
    

    打印一下该引用,输入的其实就内存地址。

    println(sayHello) // Demo02$$$Lambda$1/764977973@1fbc7afb
    

    正确写法

        sayHello()
    

    函数与方法的区别

    官方函数的定义

    1. 函数的定义:(x: Int) => x + 1
    2. 方法的定义:def add(x: Int, y: Int): Int = x + y println(add(1, 2)) // 3

    函数与方法概念

    1. 方法就是函数,函数就是一个对象
    scala> val sum=(x:Int,y:Int)=>{x+y}
    sum: (Int, Int) => Int = $$Lambda$1032/841090268@778a1250 
    
    $$Lambda$1032/841090268@778a1250  就是 sum 函数的内存地址。
    

    方法存在方法区,对象存在堆内存中。

    1. 函数调用必须带上(),否则无法调用
    2. 方法写在类中,方法是可以被重载,函数无法被重载
      方法:
      def main(args:Array[String]):Unit={
        println(sum(1, 2)) // 3
        println(sum(1, 2,4)) // 7
      }
    
      def sum(x:Int,y:Int):Int={
        x+y
      }
      def sum(x:Int,y:Int,z:Int):Int={
        x+y+z
      }
    

    但是在方法中不能重载

      def main(args:Array[String]):Unit={
        def sum(x:Int,y:Int):Int={
          x+y
        }
        def sum(x:Int,y:Int,z:Int):Int={
          x+y+z
        }
    
        println(sum(1, 2))
        println(sum(1, 2,4))
        
      }
    
    Error:(7, 9) method sum is defined twice;
      the conflicting method sum was defined at line 4:9
        def sum(x:Int,y:Int,z:Int):Int={
    

    对于函数,无论是在类中,还在方法中,都是不行的,因为函数需要定义变量名;变量名不能重复

     val sum=(x:Int,y:Int)
     val sum=(x:Int,y:Int,z:Int)
    
    1. 方法转函数:方法名 _
      def main(args:Array[String]):Unit={
    
        val a=sum _
        println(a(1,2,3))
    
      }
      
      def sum(x:Int,y:Int,z:Int):Int={
        x+y+z
      }
    
    

    函数的另一种写法

    FunctionNumNum 表示0-22个数字。最多只有23种
    Function0:表示0个参数
    Function1:表示1个参数
    Function10:表示10个参数
    Function22:表示22个参数

    依旧拿 sum为例

    val sum=(x:Int,y:Int)=>{
       x+y
    }
    

    它有两个参数;所以使用 Function2

        val sum2=new Function2[Int,Int,Int] {
          override def apply(v1: Int, v2: Int) = v1+v2
        }
    

    Function2[Int,Int,Int] :
    第一个Int:表示第一个参数的类型
    第二个Int:表示第二个参数的类型
    第三个Int:表示返回值的类型

    需要重写它的 apply 方法;在内部做运行

    override def apply(v1: Int, v2: Int)
    

    如果代码很多,是可以指定{}将代码包起来

    override def apply(v1: Int, v2: Int) = {
       v1+v2
    }
    

    对比一下原来的形式

        // 计算两个数的和
        val sum1=(x:Int,y:Int)=>{x+y}
    
        //  Function* 的形式
        val sum2=new Function2[Int,Int,Int] {
          override def apply(v1: Int, v2: Int) = {
            v1+v2
          }
        }
    

    调用

        println(s"sum1=${sum1(2,3)}") // 5
        println(s"sum2=${sum2(4,5)}") // 9
    

    结语:

    对于scala目前处于学习阶段,以上内容都是我学习的总结,至于内容质量,仁者见仁,不好的大家提出来,相互进步,能帮助你的,我也很高兴。

    相关文章

      网友评论

          本文标题:scala(五) 函数式编程

          本文链接:https://www.haomeiwen.com/subject/povryltx.html