# 方法与函数

Scala 有方法与函数,二者在语义上的区别很小。Scala 方法是类的一部分,而函数是一个对象可以赋值给一个变量。换句话来说在类中定义的函数即是方法

  • Scala 中的方法跟 Java 的类似,方法是组成类的一部分
  • Scala 中的函数则是一个完整的对象,Scala 中的函数其实就是继承了 Trait 的类的对象
  • Scala 中使用 val 语句可以定义函数def 语句定义方法
def main(args: Array[String]): Unit = {
    println(plus(1, 2))
    println(add(2, 3))
}

def add(a: Int, b: Int): Int = {
    return a + b;
}

val plus = (a: Int, b: Int)  => a + b
1
2
3
4
5
6
7
8
9
10

# 1. 函数

# 1.1 定义

def 函数名 ([参数名: 参数类型], ...)[[: 返回值类型] =] {
	语句...
	return 返回值
}
1
2
3
4
  • 函数声明关键字为def (definition)
  • [参数名: 参数类型], ...:表示函数的输入(就是参数列表), 可以没有。 如果有,多个参数使用逗号间隔
  • 函数中的语句:表示为了实现某一功能代码块
  • 函数可以有返回值,也可以没有
  • 返回值形式1: : 返回值类型 =
  • 返回值形式2: = 表示返回值类型不确定,使用类型推导完成
  • 返回值形式3: 表示没有返回值,return 不生效
  • 如果没有return ,默认以执行到最后一行的结果作为返回值

# 1.2 注意事项

  • 函数的形参列表可以是多个, 如果函数没有形参,调用时 可以不带()
  • 形参列表和返回值列表的数据类型可以是值类型和引用类型
  • Scala中的函数可以根据函数体最后一行代码自行推断函数返回值类型。那么在这种情况下,return关键字可以省略
  • 因为Scala可以自行推断,所以在省略return关键字的场合,返回值类型也可以省略
  • 如果函数明确使用return关键字,那么函数返回就不能使用自行推断了,这时要明确写成 : 返回类型 = ,当然如果什么都不写,即使有return 返回值为()
  • 如果函数明确声明无返回值(声明Unit),那么函数体中即使使用return关键字也不会有返回值
  • 如果明确函数无返回值或不确定返回值类型,那么返回值类 型可以省略(或声明为Any)
  • Scala语法中任何的语法结构都可以嵌套其他语法结构(灵活),即:函数中可以再声明/定义函数,类中可以再声明类 ,方法中可以再声明/定义方法
  • Scala函数的形参,在声明参数时,直接赋初始值(默认值),这时调用函数时,如果没有指定实参,则会使用默认值。如果指定了实参,则实参会覆盖默认值。
def sayOk(name: String = "jack"): String = {
    return name + " ok! "
}
1
2
3
  • 如果函数存在多个参数,每一个参数都可以设定默认值,那么这个时候,传递的参数到底是覆盖默认值,还是赋值给没有默认值的参数,就不确定了(默认按照声明顺序[从左到右])。在这种情况下,可以采用带名参数
def mysqlCon(addr: String = "localhost", port: Int = 3306, user: String = "root", pwd: String = "root"): Unit = {
    println("addr=" + addr)
    println("port=" + port)
    println("user=" + user)
    println("pwd=" + pwd)
}
1
2
3
4
5
6
  • Scala 函数的形参默认是val的,因此不能在函数中进行修改.
  • 递归函数未执行之前是无法推断出来结果类型,在使用时必须有明确的返回值类型
  • Scala函数支持可变参数
//支持0到多个参数
def sum(args :Int*) : Int = { 
}
//支持1到多个参数
def sum(n1: Int, args:  Int*) : Int  = { 
}
// args 是集合, 通过 for循环 可以访问到各个值。
1
2
3
4
5
6
7

# 1.3 惰性函数

惰性计算(尽可能延迟表达式求值)是许多函数式编程语言的特性。惰性集合在需要时提供其元素,无需预先计算它们,这带来了一些好处。首先,您可以将耗时的计算推迟到绝对需要的时候。其次,您可以创造无限个集合,只要它们继续收到请求,就会继续提供元素。函数的惰性使用让您能够得到更高效的代码。Java 并没有为惰性提供原生支持,Scala提供了。

# 注意事项和细节
  • lazy 不能修饰 var 类型的变量
  • 不但是 在调用函数时,加了 lazy ,会导致函数的执行被推迟,我们在声明一个变量时,如果给声明了 lazy ,那么变量值得分配也会推迟。 比如 lazy val i = 10
# java实现懒加载(其实就是java的懒汉式单例)
public class Singleton {
	
	private static volatile Singleton instance = null;

	private Singleton() {
	}

	public static Singleton getInstance() {
		if (instance == null) {
			synchronized (Singleton.class) {
				if (instance == null)
					instance = new Singleton();
			}
		}
		return instance;
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Scala实现懒加载
/**
 *  没加 lazy 关键字之前 输出如下:
 *  main 开始执行
 *  sum 开始执行
 *  sum 已调用
 *  调用结果是:3
 *
 *  加 lazy 关键字之后 输出如下:
 *  main 开始执行
 *  sum 已调用
 *  sum 开始执行
 *  调用结果是:3
 */
def main(args: Array[String]): Unit = {
    println(" main 开始执行")
    // val s = sum(1, 2)
    lazy val s = sum(1, 2)
    println(" sum 已调用")
    println(" 调用结果是:" + s)
}

def sum(a: Int, b: Int): Int = {
    println(" sum 开始执行")
    a + b
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
更新时间: 2021-06-03 21:16:13