Scala函数可以面向对象,也可以面向过程,和java不一样,只能面向对象。
一 函数定义
定义Scala函数时,需要定义函数的函数名,参数和函数体。必须
给出所有参数类型,但是不一定给出函数返回值类型只要右侧的
函数体不包含递归的语句,Scala就可以自己根据右侧表达式推断
返回类型
1.1不带返回类型
必须函数名和函数体之间可以没有=
scala>:paste
//Entering paste mode (ctrl-D to finish)
def sayHello(name:String,age:Int) {
if (age > 18) {
printf("Hi %s, you are an adult,due to you age is %d\n"
,name,age)
} else {
printf("Hi %s, you are a child,due to you age is %d\n",name,age)
}
}
//Exiting paste mode, now interpreting.
sayHello:(name: String, age: Int)Unit
scala>sayHello("nicky",15);
Hinicky, you are a child, due to you age is 15
scala>sayHello("Belly",25);
HiBelly, you are an adult, due to you age is 25
1.2带返回类型
必须函数名和函数体之间有=,如果没有代表没有返回值
scala>:paste
//Entering paste mode (ctrl-D to finish)
def sayHello(name:String,age:Int) = {
if (age > 18) {
printf("Hi %s, you are an adult,due to you age is %d\n",name,age)
name+age
} else {
printf("Hi %s, you are a child,due to you age is %d\n",name,age)
name+age
}
}
//Exiting paste mode, now interpreting.
sayHello:(name: String, age: Int)String
scala>print(sayHello("Belly",25));
HiBelly, you are an adult, due to you age is 25
Belly25
1.3单行函数可以不用括号
scala>def countNum(count:Int) =print("count="+count)
countNum:(count: Int)Unit
scala>countNum(20);
count=20
综合练习:
scala>:paste
//Entering paste mode (ctrl-D to finish)
defsum(count:Int) = {
var result = 0
for(i <- 1 to count){
result += i
}
result
}
//Exiting paste mode, now interpreting.
sum:(count: Int)Int
scala>sum(20);
res18:Int = 210
1.4递归函数
如果函数体内递归调用函数自身,则必须手动给出函数的返回类型。
scala>:paste
//Entering paste mode (ctrl-D to finish)
deffab(n: Int): Int = {
if(n <= 1) 1
else fab(n - 1) + fab(n - 2)
}
//Exiting paste mode, now interpreting.
fab:(n: Int)Int
二 函数参数
2.1默认参数
在调用函数的时候,我们可能不想传入某个参数值,而使用默认的
参数值。
Java实现,我们需要判断这个参数是否为空,如果为空,则给一个
默认值
publicvoid connect(String host,String port){
if (host == null) {
host = "localhost";
}
if (port == null) {
port = "9000";
}
}
scala>:paste
//Entering paste mode (ctrl-D to finish)
defhello(name:String, age:Int = 20) {
print("Hello,"+name+", yourage is "+ age)
}
//Exiting paste mode, now interpreting.
hello:(name: String, age: Int)Unit
scala>hello("nicky");
Hello,nicky,your age is 20
如果给出参数不够,从左往右依次应用参数
2.2带名参数
我们传入参数的时候,可以不根据签名顺序传入参数,也就是不按照
参数定义顺序传入参数,那这时候我们在调用函数的时候指定参数名
和参数值
scala>:paste
//Entering paste mode (ctrl-D to finish)
defconnect(host:String, port:String,username:String,password:String) {
println("Host:"+host+">> port: " +port+">> username:"+username
+"password:"+password)
}
//Exiting paste mode, now interpreting.
connect:(host: String, port: String, username: String, password: String)Unit
scala>connect(username = "root",port = "3306", password ="123456",
host= "hadoop-cluster-01")
Host:hadoop-cluster-01>> port: 3306>> username: rootpassword: 123456
java里面,我们必须严格按照参数顺序来传递参数
2.3可变长参数
有时候我们需要将函数参数定义为参数个数可变的形式,此时可以使用变长参数
Java实现:
publicint sum(int... nums){
int result = 0;
for (int num :nums) {
result += num;
}
return result;
}
Scala实现:
scala>:paste
//Entering paste mode (ctrl-D to finish)
defsum(nums:Int*) = {
var result = 0;
for(num <- nums){
result += num
}
result
}
//Exiting paste mode, now interpreting.
sum:(nums: Int*)Int
scala>sum(10,20,30);
res31:Int = 60
2.4使用序列调用变长参数
如果想要将一个序列直接调用变长参数函数,是不对的。比如:
valresult = sum(1 to 5);此时需要使用Scala特殊的语法将参数定义为序列,
让Scala解释器能够识别到。
诸如: valresult = sum(1 to 5:_*);
nums.length:可变参数的长度
nums.head:可变参数第一个值
nums.tail:可变参数第一个值以外的其他参数值
defsum2(nums: Int*): Int = {
if (nums.length == 0) 0
else nums.head + sum2(nums.tail: _*)
}
三 函数过程
Scala中,定义函数的时候,函数体前面没有=号,返回类型时Unit
,类似于javavoid 返回类型,这种函数没有返回类型,被称之为
过程。简而言之,没有返回类型的函数就是过程
过程的三种写法:
defsayHello(name: String) = "Hello, " + name
defsayHello(name: String) { print("Hello, " + name); "Hello, "+ name }
defsayHello(name: String): Unit = "Hello, " + name
四 函数lazy值
在Scala中,提供了lazy值特性,也就是说,如果将一个变量声明为
lazy,则只有在第一次使用该变量的时候,变量对应的表达式才
会发生计算。这种特性对于特别耗时的计算机操作特别有用,比
如打开文件进行IO,进行网络IO
立马读取文件
vallines = fromFile("C:/Users/nickyzhang/Desktop/info.txt").mkString
hellonicky
懒读取文件内容
scala>lazy val lines = fromFile("C:/Users/nickyzhang/Desktop/info.txt").mkString
lines:String = <lazy>
#第一次使用lines
scala>print(lines);
hellonicky
deflines = fromFile("C:/Users/nickyzhang/Desktop/info.txt").mkString
#调用函数,也会立马读取内容
lines
hellonicky
五 函数异常
在Scala中,异常处理和捕获机制与Java是非常相似的
try{
throw new IllegalArgumentException("xshould not be negative")
}catch {
case _: IllegalArgumentException =>println("Illegal Argument!")
}finally {
print("release resources!")
}
scala>import java.io._
importjava.io._
scala>:paste
//Entering paste mode (ctrl-D to finish)
try{
throw new IOException("user definedexception")
}catch {
case e1: IllegalArgumentException =>println("illegal argument")
case e2: IOException => println("ioexception")
}
//Exiting paste mode, now interpreting.
ioexception