05定义方法

本文最后更新于 2021-08-05 11:42:59

定义方法

  • 如果函数签名和函数体之间的 =省略,这个函数返回Unit
  • 函数调用的的时候,如果参数个数为0,则调用时括号可以省略
  • 如果函数声明的时候,不需要传递参数,在定义时可以不加括号,调用的时候也不能加括号
  • 函数的参数默认值都是 val ,所以不能更改参数值,若要更改,只能重新定义一个局部变量
  • 函数声明的时候,参数可以带默认值
  • 默认返回最后一行的值,scala会根据最后一行代码进行推导
    • 有return 不能推导
    • 返回值类型和推导类型不一致的时候不要推导
    • 递归调用的时候不能推导
  • scala默认是按照位置传参,也可以按照命名传参
object FunctionDemo1 {
  def main(args: Array[String]): Unit = {
    println(add(1, 2))
    //没有参数传递 可以不加括号
    my_print
    my_print2
    //通过命名传参
    println(add(val1 = 1, val2 = 2))
  }

  def add(val1:Int,val2:Int):Int={
     val1+val2
  }
  //自动推导返回值
  def add2(val1:Int,val2:Int)={
    val1+val2
  }

  def my_print(): Unit ={
    println("1111")
  }
  //没有参数传递 可以不加括号,调用方法时就不能带括号
  def my_print2: Unit ={
    println("222")
  }

  def default_value(val1:Int=1,val2:Int=2)= val1+val2
}
  • 函数可以定义在任何位置,定义在函数的内部,外部不能调用
  • 可以将内部的函数作为返回值,外部即可调用
  • 可以将函数作为一个参数,传递给另外一个函数
  • 函数可以作为值传递,方法不行
  • def定义的严格意义上来说 都是方法
  • 在有上下文环境下,比如明确指定了 接收为一个函数,方法可以自动转换为函数
object FunctionDemo2 {
  def main(args: Array[String]): Unit = {
    fun1
    //返回函数并调用
    val fun22 = fun2()
    fun22()

    //将函数整体做为参数
    func3(func33 _)
    //priv.king.function.FunctionDemo2$$$Lambda$6/2101440631@7dc36524

    //直接定义函数
    //函数不能声明返回值类型,只能靠推导 在参数列表后面不能指定返回值
    //可以通过 _ 把方法转换成函数
    //如果接收类型指定函数类型,后面可以不加 _ 会自动转换成函数
    val f:Int=>Int=(a:Int)=>{a*a}
  }
  //函数可以定义在任何位置
  //在函数内部定义函数
  def fun1()={
    fun11

    def fun11()={
      println("111")
    }
  }


  //将函数作为返回值
  def fun2()={
    def fun22()={
      println("22")
    }
    //将fun22(方法)转换为函数
    fun22 _
  }

  def func3(x:(Int,Int)=>Unit)={
      x(1,2)
      println(x)
  }

  def func33(val1:Int,val2:Int)={
    println("333"+val1+val2)
  }
}

匿名函数

object FunctionDemo3 {
  def main(args: Array[String]): Unit = {
    //使用lambda表达式 匿名函数
    fun1(()=>{
      println("1111")
    })

    func2((a:Int,b:Int)=>{a+b})
    //已经指定必须为Int 所以可以省略
    func2((a,b)=>a+b)
    //参数只使用一次 可以使用 _ 代替,
    //第一个 _ 表示第一个参数,第二个 _ 表示第二个参数 .....
    func2(_ + _)
  }

  def fun1(f:()=>Unit): Unit ={
    f()
  }

  def func2(f:(Int,Int)=>Int)={
    println(f(1,2))
  }
}

模拟foreach reduce map filter

object FunctionDemo4 {
  def main(args: Array[String]): Unit = {
    val arr1 = Array(10, 20, 30, 40, 50)
    foreach(arr1, param => println(param))
    foreach(arr1, println)

    val arr2 = filter(arr1, _ % 2 == 0)
    foreach(arr2, x=>print(s"$x\t"))


    println()
    val arr3 = map(arr1,x=>x*x)
    foreach(arr3, x=>print(s"$x\t"))

    println()

    var reduce_res = reduce(arr1,_+_)
    println(reduce_res)
  }

  def foreach(arr: Array[Int], op: Int => Unit) = {
    for (elem <- arr) {
      op(elem)
    }
  }

  def filter(arr: Array[Int], condition: Int => Boolean): Array[Int] = {
    for (i <- arr if condition(i)) yield {
      i
    }
  }

  def map(arr:Array[Int],op:Int=>Int):Array[Int]={
      for(elem<-arr) yield op(elem)
  }


  def reduce(arr:Array[Int],op:(Int,Int)=>Int): Int ={
      var param1 = arr(0);
    for(i<- 1 until arr.length-1){
      param1=op(param1,arr(i))
    }
    param1
  }

}

闭包

object FunctionDemo5 {
  def main(args: Array[String]): Unit = {
    val f = foo()
    val r = f(10)
    println(r) //20

    val f1 = foo2()
    println(f1()) //11
    println(f1()) //12
    val f2 = foo2()
    println(f2()) //11
  }

  def foo() = {
    //a相当于外部变量
    var a = 10
    b: Int => a + b
  }


  def foo2() = {
    var a = 10
    ()=>{a+=1;a}
  }
}

/*
闭包:
一个函数访问了外部的局部变量,则这个函数和它访问的局部变量称为闭包
闭包会阻值外部局部变量的销毁
 */
class Outer{
    private int ccc;

    public void fun1(){
        int a=1;

        final int b = 2;
        class Innor{
            public void fun2(){
//                System.out.println(a);   error
                System.out.println(b);
                System.out.println(ccc);
            }
        }
        //为什么在内部类中传递的参数(局部变量)必须是final
        //不是final就是因为局部变量保存在栈中,栈弹出,变量就没有了
        //声明为final就是常量
        //主要还是看变量会不会出现生命周期不一致问题
        //导致原因还是java没有闭包
        new Thread(()->{
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //如果不是final,是一个局部变量
            //这里方法内的局部变量就不存在了
            Innor innor = new Innor();
            innor.fun2();
        }).start();
    }
}

class Outer2{
    final int b =11;
    
    class Innor2{
        final int b=1;
        
        public void fun(){
            //就近原则 访问自己的b
            System.out.println(b);
            //访问外部类的b
            System.out.println(Outer2.this.b);
        }
    }
}

05定义方法
https://jiajun.xyz/2020/11/02/scala/05定义方法/
作者
Lambda
发布于
2020年11月2日
更新于
2021年8月5日
许可协议