Scala方法与函数使用和定义详解

 更新时间:2022年12月14日 14:36:01   作者:Cry丶  
这个章节会很烧脑,需要认真研读,我会尽量写的详细一些。 方法和函数,看似是两个概念,其实他严格来说也是两个概念,但我们大可以理解成是同一个概念,在使用时只有语法上的细微差别,是很类似的,都理解为function即可

一、方法的定义

1.方法体中最后返回值可以使用return, 如果使用了return, 那么方法体的返回值类型一定要指定

2.如果方法体重没有return, 默认将 方法体中最后一行计算的结果当作返回值返回. 方法体的返回值可以省略, 会自动推断

3.定义方法传入的参数一定要指定类型

4.方法的方法体如果只有一行, 那么方法体的“{…}”可以省略

5.如果定义方法时, 省略了方法名称和方法体之间的"=", 那么无论方法体最后一行计算的结果是什么, 都会被丢弃, 返回Unit

def max(a: Int, b: Int) = {
  if (a > b) {
    "哈哈"
  } else {
    b
  }
}
// 语法糖: 方法定义
def max0(a: Int, b: Int) = if (a > b) a else b

注:记住def定义的格式,按着格式敲即可,不要纠结

二、递归方法

递归方法必须要显示指定返回体的类型

def fun2(num: Int): Int = {
  if (num == 1)
    num
  else
    num * fun2(num - 1)
}
// 语法糖
def fun2(num:Int) : Int = if (num == 1) num else num * fun2(num - 1)

注:编译器无法直接推断出你最终递归的结果类型,所以需要你显示指定

三、参数有默认值的方法

1.默认值的函数中,如果传入的参数个数与函数定义相同,则传入的数值会覆盖默认值

2.如果不想覆盖默认值,传入的参数个数小于定义的函数的参数,则需要指定参数名称

def fun3(a: Int = 10, b: Int) = {
  println(a + b)
}

四、可变参数个数的函数

多个参数之间逗号分开

def fun4(elements: Int*) = {
  println(elements)
  elements.foreach(i => println(i))
  // 当匿名函数的元素只用到一次的时候, 可以用_简写
  elements.foreach(println(_))
  // 当方法入参为单个参数时且正好是匿名函数的元素时, 进一步简写
  elements.foreach(println)
  var sum = 0;
  for (elem <- elements) {
    sum += elem
  }
  sum
}

五、匿名函数

注意函数的写法与方法的写法有些许的不同,出现 => 符号就认为是函数,但实际使用上效果并无不同,仅仅是语法上的细微区别

原生的匿名函数写法(基本不用):(Int, Int) => Int就是他的类型

/**
 * 原生的匿名函数写法(基本不用)
 * @return
 */
def fun: (Int, Int) => Int = (a: Int, b: Int) => {
  a + b
}

常用的匿名函数写法: 可以将匿名函数返回给定义的一个变量, 看到“=>”就是匿名函数, 多用于方法的参数是函数时(函数指针),用匿名函数简写

/**
 * 常用的匿名函数写法: 可以将匿名函数返回给定义的一个变量, 看到“=>”就是匿名函数
 * 多用于方法的参数是函数时(函数指针),用匿名函数简写
 *
 * @param args
 */
def main(args: Array[String]): Unit = {
  /**
   * 有参数匿名函数
   */
  val value1: (Int) => Unit = (a: Int) => {
    println(a)
  }
  value1(1)
  /**
   * 无参数匿名函数
   */
  val value2 = () => {
    println("我爱学习")
  }
  value2()
  /**
   * 有返回值的匿名函数
   */
  val value3 = (a: Int, b: Int) => {
    a + b
  }
  println(value3(4, 4))
}

六、嵌套方法

/**
 * 嵌套方法
 * 例如:嵌套方法求5的阶乘
 */
def fun5(num: Int) = {
  def fun6(a: Int, b: Int): Int = {
    if (a == 1) {
      b
    } else {
      fun6(a - 1, a * b)
    }
  }
  fun6(num, 1)
}

七、偏应用函数(部分应用函数)

某些情况下, 方法中参数非常多, 调用这个方法非常频繁, 每次调用只有固定的某个参数变化, 其他都不变, 可以定义偏应用来实现

def showLog(date :Date, log :String)= {
  println(s"date is $date, log is $log")
}
def main(args: Array[String]): Unit = {
  val date = DateUtil.date(new Date())
  showLog(date,"当前时间")
  // 想要调用log, 以上变化的是第二个参数, 可以用偏应用函数处理
  // 把showLog()方法定义为偏应用函数
  val logWithDate = showLog(date,_:String)
  // 第二种函数写法
  def logWithDate2 = showLog(date,_:String)
  logWithDate("偏应用函数-log11")
  logWithDate("偏应用函数-log22")
  logWithDate("偏应用函数-log33")
}

八、高阶函数

函数的参数是函数,或者函数的返回类型是函数,或者函数的参数和函数的返回类型是函数的函数.

  /**
   * 普通的方法
   *
   * @param a
   * @param b
   * @return
   */
  def fun(a: Int, b: Int): Int = {
    a + b
  }
  /**
   * 使用 _把方法强转为一个函数
   */
  private val function: (Int, Int) => Int = fun _
  /**
   * 函数的参数是函数: 函数的类型 (Int, Int) => Int, 记住: 方法的引用仅为方法本身,需要重新赋实参
   *
   * @param f 函数作为参数
   * @param a
   * @return
   */
  def fun1(f: (Int, Int) => Int, a: Int): Int = {
    f(a, 100)
  }
  /**
   * 函数的返回是函数: 必须要显示地写出返回值类型, 或者使用 f2 _
   *
   * @param a
   * @param b
   * @return
   */
  def fun2(a: Int, b: Int): (Int, Int) => Int = {
    // 在内部定义了一个方法
    def f2(v1: Int, v2: Int): Int = {
      v1 + v2 + a + b
    }
    f2
  }
  /**
   * 函数的参数是函数,函数的返回是函数
   *
   * @param f
   * @return
   */
  def fum3(f: (Int, Int) => Int): (String, String) => String = {
    val i = f(1, 2)
    def fun1(s1: String, s2: String): String = {
      s1 + "@" + s2 + "$" + i
    }
    fun1
  }
  /**
   * 函数入口
   *
   * @param args
   */
  def main(args: Array[String]): Unit = {
    // 显示声明过的函数作为参数
    println("显示声明过的函数作为参数: " + fun1(fun, 100))
    // 匿名函数作为参数: 匿名函数入参的类型可以省略不写
    println("匿名函数作为参数: " + fun1((a: Int, b: Int) => {
      a * b
    }, 100))
    // 返回值是一个函数
    println("返回值是一个函数: " + fun2(1, 2)(3, 4))
    // 入参和出参都是函数
    println("入参和出参都是函数: " + fum3(fun)("hello", "scala!"))
    println("入参和出参都是函数: " + fum3((a, b) => a * b)("hello", "scala!"))
  }

笔者注:高阶函数这块内容会相对较为难以理解,可以先记住这种结构

九、柯里化函数

柯里化函数: 本质上就是对返回值是函数的方法的一种简化写法

def fun7(a: Int, b: Int)(c: Int, d: Int) = {
  a + b + c + d
}
/**
 * 函数入口
 *
 * @param args
 */
def main(args: Array[String]): Unit = {
  println(fun7(1, 2)(3, 4))
}

注:fun7(1, 2)(3, 4)可以理解成先运算fun7(1,2)返回了一个fun7函数对象,再对他进行参数(3,4)的赋值

到此这篇关于Scala方法与函数使用和定义详解的文章就介绍到这了,更多相关Scala方法与函数内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java 继承与多态超详细梳理

    Java 继承与多态超详细梳理

    继承就是可以直接使用前辈的属性和方法。自然界如果没有继承,那一切都是处于混沌状态。多态是同一个行为具有多个不同表现形式或形态的能力。多态就是同一个接口,使用不同的实例而执行不同操作
    2022-04-04
  • Java字符转码之UTF-8互转GBK具体实现

    Java字符转码之UTF-8互转GBK具体实现

    在Java程序中字符串默认的编码方式是UTF-16编码,因此需要将GBK编码转换为UTF-8编码,主要是为了避免出现乱码的情况,这篇文章主要给大家介绍了关于Java字符转码之UTF-8互转GBK具体实现的相关资料,需要的朋友可以参考下
    2023-11-11
  • 关于Java中静态代码块的执行浅析

    关于Java中静态代码块的执行浅析

    这篇文章主要给大家介绍了关于Java中静态代码块执行的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。
    2017-09-09
  • SpringBoot异常处理之异常显示的页面问题

    SpringBoot异常处理之异常显示的页面问题

    这篇文章主要介绍了SpringBoot异常处理异常显示的页面的问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-09-09
  • 图解JAVA中Spring Aop作用

    图解JAVA中Spring Aop作用

    这篇文章主要介绍了Java的Spring框架下的AOP的作用,需要的朋友可以参考
    2017-04-04
  • Java KeyGenerator.generateKey的19个方法代码示例

    Java KeyGenerator.generateKey的19个方法代码示例

    在下文中一共展示了KeyGenerator.generateKey方法的19个代码示例,这些例子默认根据受欢迎程度排序
    2021-12-12
  • jsch中ChannelShell与ChannelExec的区别及说明

    jsch中ChannelShell与ChannelExec的区别及说明

    这篇文章主要介绍了jsch中ChannelShell与ChannelExec的区别及说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • java正则表达式简单使用和网页爬虫的制作代码

    java正则表达式简单使用和网页爬虫的制作代码

    java正则表达式简单使用和网页爬虫的制作代码,需要的朋友可以参考一下
    2013-05-05
  • Http学习之组装报文

    Http学习之组装报文

    这篇文章主要介绍了Http学习之组装报文,组装报文就是指组装HTTP响应报文,你需要返回客户请求的相应资源,通常一个完整的报文包括报文头和报文体,一起来看看吧
    2023-04-04
  • SpringBoot中实现定时任务的几种方式

    SpringBoot中实现定时任务的几种方式

    定时任务在我们项目开发中也是很重要的,对于某些场景必须要用定时任务 ,如定时发送邮件啊,定时统计数据等,这篇文章主要讲讲项目中实现定时任务的几种方式,需要的朋友可以参考下
    2023-05-05

最新评论