鲁春利的工作笔记,好记性不让烂笔头
函数定义
def 函数名(参数列表) : 返回类型 = {函数体}
说明:
返回类型默认为空(Unit,类似于Java的void);
函数体中默认最后一行为该函数的返回值;
函数如果有返回值,则=号是必须的,否则可以省略等号;
如果函数有返回值但返回类型指定为Unit,则任然无返回值;
函数体中是不建议使用return语句的,但如果出现了return语句,则必须指定返回类型。
1、无返回值的函数举例
package com.lucl.scala /** * @author lucl */ object ClassWithUnitFunc { def sayHi (name : String) { // 无返回值,=号被省略 println("hello, " + name); } def main (args : Array[String]) { sayHi("luchunli"); // hello, luchunli println("sayHi return , " + sayHi("luchunli")); // sayHi return , () } }
说明:Unit为无返回值,调用时返回()
2、有返回值的函数举例
package com.lucl.scala /** * @author lucl */ object ClassWithReturnValFunc { def sayBye (name : String) { "bye, " + name; } def sayOk (name : String) = { "ok, " + name; } // 有return必须给定返回类型 def sayGood (name : String) : String = { // method sayGood has return statement; needs result type return "good, " + name; } def main (args : Array[String]) { println(sayBye("luchunli")); // () println(sayOk("luchunli")); // ok, luchunli println(sayGood("luchunli")); // good, luchunli } }
3、方法调用
无参方法调用时可以省略括号;
有参方法调用时必须带括号及参数。
package com.lucl.scala /** * @author luchunli */ object FuncTest { // 无参函数 def greet () { println("greet"); } // 有参函数 def hello (name : String) { println("hello, " + name); } // 函数只有一条语句,{}也可以省略 def goodbye = println("good bye"); def main (args : Array[String]) { greet; // 无参函数调用时可以省略() greet(); // hello("luchunli"); // 有参函数不可省略 println(greet() == ()); // true goodbye; // good bye } }
4、默认参数
有些情况下我们不需要给出全部参数,可以使用默认参数,但需要知道参数顺序或者参数名称。
package com.lucl.scala /** * @author luchunli */ object FuncDefaultArguments { def sayHi (word : String, name : String = "luchunli") { println(word + ", " + name); } def main (args : Array[String]) { sayHi("hello"); // hello, luchunli // 通过名称指定参数 sayHi(word="hello"); // hello, luchunli sayHi(word="hi", "zhangsan"); // hi, zhangsan } }
5、变长参数
实现一个可以接受可变长度的参数列表的函数。
package com.lucl.scala /** * @author lucl */ object FuncWithVarargs { def vsum (args : Int*) { var result = 0; for (arg <- args) { result += arg; } println("The result " + result); // The result 15 } def sayHi (args : String*) { print("Hi, "); args.foreach {print}; // luchunlizhangsanlisi println; } // 在递归中我们同样可以使用这种方式,Scala编译器不能推断递归函数的返回类型,必须给定。 def sum2(args : Int*) : Int = { if(args.length == 0 ) { 0 } else { // 序列的head是参数args的首个元素,而tail是所有其它的元素序列 args.head + sum2(args.tail: _*) } } def main(args : Array[String]) { vsum(1, 2, 3, 4, 5); // 实现一个序列作为参数传入,需要追加 _*,告诉编译器希望把这个参数当做序列处理。如: vsum(1 to 5 : _*); // 将1到5当做参数序列处理 sayHi("luchunli", "zhangsan", "lisi"); // println(sum2(1 to 5 : _*)); // 15 } }
实际上Java中也支持这种动态参数:
package com.lucl.apps.web.sample; /** * @author luchunli * */ public class JavaDynamicParams { public void sayHi (String ...params) { for (String str : params) { System.out.print(str + ", "); // luchunli, zhangsan, lisi, } System.out.println(""); } // public static void main(String[] args) { JavaDynamicParams dy = new JavaDynamicParams(); dy.sayHi("luchunli", "zhangsan", "lisi"); } }
6、局部函数
实际上就是在函数里面再定义一个函数。
package com.lucl.scala import scala.io.Source import java.io.File /** * @author luchunli */ object FuncWithPart { def processFile () { val file = new File("F:\\ftpfile\\ip.txt"); var source = Source.fromFile(file); for (line <- source.getLines()) { processLine (line); } // 定义局部函数,只在当前函数范围内有效 def processLine (x : String) { if (null == x || "".equals(x.trim)) { // 去掉空行 // ... } if ((x indexOf "*") != -1) { // 去掉无效的数据行 // ...... } println("Line : " + x); } } def main(args : Array[String]) { processFile(); } }
7、匿名函数
Scala把函数当作内置的值,也就是说函数可以放进var或val中,并和其他任何值所受的对待毫无二致,被称为函数字面值或匿名函数。
定义函数字面值,关键是箭头=>,定义格式如下:
(函数参数列表) => {作为代码块的函数体}
package com.lucl.scala /** * @author luchunli */ object FuncOfAnonymity { // 省略代码块的{} var doubler = (x : Int) => x * 2; // 匿名函数传入n之后得到的仍然是个匿名函数 // 即函数的函数,接收一个值并返回一个新的函数字面值: val adder = (n : Int) => { (x : Int) => x + n; } // 无参匿名函数 var noParam = () => println("Hello World!"); // 函数作为参数,格式为def 函数名(函数名:(参数类型, 参数类型, ...) => 返回值, 其他参数) def processNum (f : (Int, Int) => Int, m : Int, n : Int) { println(f (m, n)); // 5 } def main (args : Array[String]) { println(doubler(3)); // 6 println(adder(3)); // <function1> var plug = adder(3); // 获得一个函数 println(plug(2)); // 5 noParam(); // Hello World!,而noParam表示的为() val add = (a : Int, b : Int) => a + b; processNum(add, 2, 3); } }