一、方法的定义
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方法与函数内容请搜索好代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持好代码网!