1、方法中的return是可以缺省的,scala会将函数的最后一句作为返回值;
方法还可以缺省返回值类型,scala会自动进行类型推断,但是如果是递归函数就必须指定返回这类型。但是最好还是不要省略返回值类型
2、scala中的参数和Java中的参数不太一样。Java参数有形参和实参的区别,但在scala中有时形参和实参是一致的。参看【scala指定函数参数名】
3、=>左侧表示输入,右侧表示转换操作
4、scala函数中的参数都是val的,所以不能在函数体内再次给参数赋值
5、Scala定义函数的方法
:
6、函数的传值调用和传名调用:传值调用就是普通意义上的调用;着重说下传名调用。其语法是: def addByName(a: => Int) = a 比传值调用多了一个=>,传名调用只有在函数体中实际调用时才会计算表达式的值,只是两个调用方式的最大区别。
Scala除了支持面向对象之外,还是一门函数式语言,因此函数是Scala的核心。
定义函数,需要给出函数的名字、参数和函数体:
def method(x: Int) = if(x>0) x else -x
函数需要给出所有参数的类型。只要函数不递归是可以不写return,scala可以根据=右边的式子推导出函数的返回值类型。
函数要定义在object中,红框中的叫函数声明。如果不写等号和方法体,则方法会被隐式的声明为“抽象abstract”。对于函数的调用,跟Java的方式一样。使用对应的函数名,如果有参数,传入对应的参数即可调用。
如果函数体需要多个表达式来完成需求,可是使用代码块。代码块中的最后一句就是函数的返回值。如下例:如果要使用return返回 a+b的值,则必选要标明函数的返回类型
【过程】
scala对于不返回值的函数有特使的表示方法:如果函数体包含在花括号中但是没有前面的=,那么返回类型就是Unit,这样的函数就叫做过程。过程不返回值,调用过程是为了使用它的副作用。如:我们需要打印一些图案,那么就可以定义如下过程:
def
main(args: Array[
String
]): Unit = {
draw("123")
}
//draw(s:String){} 对于没有返回这的过程,这种写法也是对的
def
draw(s:
String
): Unit ={
println("-----")
println("|"+" "+"|")
println("|"+s+"|")
println("|"+" "+"|")
println("-----")
}
【默认参数值】
在scala函数中,可以为函数的参数指定默认值。当我们调用这个函数没有给参数传值的时候,就会启用默认参数值。如果指定了参数值,就会使用指定的参数值。
在下面这个例子中的第三个输出语句中,我们还可以不按照参数顺序来传值,但是需要在传值的时候指定参数名
object
HelloWorld {
def
main(args: Array[
String
]): Unit = {
println
(
outputBook
(
"book1"
));
println
(
outputBook
(
"book2"
,
"["
,
"]"
));
println
(
outputBook
(right=
"***]"
,bookname =
"book3"
))
}
def
outputBook(bookname:
String
,left:
String
=
"{"
,right:
String
=
"}"
) =
left + bookname + right;
}
//运行结果
{book1}
[book2]
{book3***]
【可变参数】
scala支持可变参数,实现方式与Java稍有不同。scala的变长参数是用 * 声明。本例中,如果想要实现一个序列作为参数传入,需要追加 _*,意思就是告诉编译器把这个参数当做参数序列处理。
直接传入一个序列使错误的,因为这这个例子中,传入的参数被限制为单个参数,所以直接传入一个整数区间是不被接受的。解决办法就是在序列后面追加 _*,来告诉编译器我们希望这个参数被当做单数序列处理。
def
main(args: Array[
String
]): Unit = {
println
(
sum
(
1
,
2
,
3
,
4
,
5
))
//
序列作为参数
println
(
sum
(
1
to
5
: _*))
}
//
变长参数
def
sum(args: Int*): Int ={
var
res =
0
for
(n <- args){
res += n;
}
return
res;
}
///
【Scala指定函数参数名】
通常情况下,我们想调用一个参数都是按照函数定义的参数顺序一个个传递。在scala中我们也可以通过指定函数的参数名,而不一定需要按照函数定义的参数顺序向函数传递参数。
def
main(args: Array[
String
]): Unit = {
printInt
(b=
5
, a=
8
);
}
def
printInt(a: Int, b: Int): Unit = {
println
(a);
println
(b);
【Scala函数的调用】
1、传值调用,这种方式就是Java中最常见的函数调用方式。
def
main(args: Array[
String
]): Unit = {
var
increase = (x: Int) => x+
1
println(increase(10))
println("2:"+increase2(13))
}
//相当于这种形式 这种写法是极简写法,省略了返回类型、返回值和方法体的括号
def
increase2(x: Int) = x+
1
;
//如果是多个语句的情况
val
increaseAnother = (x: Int) =>{
println("多条语句")
println
(
"
请使用
\"
{}
\"
"
)
x +
1
}
println
(increaseAnother(
12
))
2、传名调用,将未计算的表达式传进函数。传名调用的语法是:在使用传名调用时,在参数名称和参数类型之间有一个"=>"符号。传名调用是在函数内部进行表达式值计算的。而传值调用在传入函数内部之前就已经把参数表达式的值计算完毕。
示例代码如下:
=>左侧表示输入,右侧表示转换操作
def
main(args: Array[
String
]): Unit = {
//函数的传名调用
delayed(time())
}
def
time() ={
println("time方法,获取时间")
System.nanoTime()
}
def
delayed(t: => Long) = {
println("在delayed方法中调用time方法");
//在真正调用参数t的时候才会开始计算t的值
println("参数t:"+t);
//又调用了一次time()来计算t的值
t
}
在main方法中我们调用了delayed方法,传的参数是time()。delayed方法通过 =>符号来设置传名调用。
运行结果:
在运行的时候,首先进入delayed方法。接着delayed方法打印了接收到的值,这一步就在delayed内部执行了time方法。最后再次通过参数t调用了time()方法。
【匿名函数】
scala中定义匿名函数的语法很简单。箭头左边是参数列表,右边是函数体
def
main(args: Array[
String
]): Unit = {
//定义一个匿名函数
var
inc = (x: Int) => x+
1
;
println(inc(20))
}