05定义方法

本文最后更新于 2021-08-05 11:42:59

定义方法

  • 如果函数签名和函数体之间的 =省略,这个函数返回Unit
  • 函数调用的的时候,如果参数个数为0,则调用时括号可以省略
  • 如果函数声明的时候,不需要传递参数,在定义时可以不加括号,调用的时候也不能加括号
  • 函数的参数默认值都是 val ,所以不能更改参数值,若要更改,只能重新定义一个局部变量
  • 函数声明的时候,参数可以带默认值
  • 默认返回最后一行的值,scala会根据最后一行代码进行推导
    • 有return 不能推导
    • 返回值类型和推导类型不一致的时候不要推导
    • 递归调用的时候不能推导
  • scala默认是按照位置传参,也可以按照命名传参
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
26
27
28
object FunctionDemo1 {
def main(args: Array[String]): Unit = {
println(add(1, 2))
//没有参数传递 可以不加括号
my_print
my_print2
//通过命名传参
println(add(val1 = 1, val2 = 2))
}

def add(val1:Int,val2:Int):Int={
val1+val2
}
//自动推导返回值
def add2(val1:Int,val2:Int)={
val1+val2
}

def my_print(): Unit ={
println("1111")
}
//没有参数传递 可以不加括号,调用方法时就不能带括号
def my_print2: Unit ={
println("222")
}

def default_value(val1:Int=1,val2:Int=2)= val1+val2
}
  • 函数可以定义在任何位置,定义在函数的内部,外部不能调用
  • 可以将内部的函数作为返回值,外部即可调用
  • 可以将函数作为一个参数,传递给另外一个函数
  • 函数可以作为值传递,方法不行
  • def定义的严格意义上来说 都是方法
  • 在有上下文环境下,比如明确指定了 接收为一个函数,方法可以自动转换为函数
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
object FunctionDemo2 {
def main(args: Array[String]): Unit = {
fun1
//返回函数并调用
val fun22 = fun2()
fun22()

//将函数整体做为参数
func3(func33 _)
//priv.king.function.FunctionDemo2$$$Lambda$6/2101440631@7dc36524

//直接定义函数
//函数不能声明返回值类型,只能靠推导 在参数列表后面不能指定返回值
//可以通过 _ 把方法转换成函数
//如果接收类型指定函数类型,后面可以不加 _ 会自动转换成函数
val f:Int=>Int=(a:Int)=>{a*a}
}
//函数可以定义在任何位置
//在函数内部定义函数
def fun1()={
fun11

def fun11()={
println("111")
}
}


//将函数作为返回值
def fun2()={
def fun22()={
println("22")
}
//将fun22(方法)转换为函数
fun22 _
}

def func3(x:(Int,Int)=>Unit)={
x(1,2)
println(x)
}

def func33(val1:Int,val2:Int)={
println("333"+val1+val2)
}
}

匿名函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
object FunctionDemo3 {
def main(args: Array[String]): Unit = {
//使用lambda表达式 匿名函数
fun1(()=>{
println("1111")
})

func2((a:Int,b:Int)=>{a+b})
//已经指定必须为Int 所以可以省略
func2((a,b)=>a+b)
//参数只使用一次 可以使用 _ 代替,
//第一个 _ 表示第一个参数,第二个 _ 表示第二个参数 .....
func2(_ + _)
}

def fun1(f:()=>Unit): Unit ={
f()
}

def func2(f:(Int,Int)=>Int)={
println(f(1,2))
}
}

模拟foreach reduce map filter

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
object FunctionDemo4 {
def main(args: Array[String]): Unit = {
val arr1 = Array(10, 20, 30, 40, 50)
foreach(arr1, param => println(param))
foreach(arr1, println)

val arr2 = filter(arr1, _ % 2 == 0)
foreach(arr2, x=>print(s"$x\t"))


println()
val arr3 = map(arr1,x=>x*x)
foreach(arr3, x=>print(s"$x\t"))

println()

var reduce_res = reduce(arr1,_+_)
println(reduce_res)
}

def foreach(arr: Array[Int], op: Int => Unit) = {
for (elem <- arr) {
op(elem)
}
}

def filter(arr: Array[Int], condition: Int => Boolean): Array[Int] = {
for (i <- arr if condition(i)) yield {
i
}
}

def map(arr:Array[Int],op:Int=>Int):Array[Int]={
for(elem<-arr) yield op(elem)
}


def reduce(arr:Array[Int],op:(Int,Int)=>Int): Int ={
var param1 = arr(0);
for(i<- 1 until arr.length-1){
param1=op(param1,arr(i))
}
param1
}

}

闭包

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
26
27
28
29
30
31
object FunctionDemo5 {
def main(args: Array[String]): Unit = {
val f = foo()
val r = f(10)
println(r) //20

val f1 = foo2()
println(f1()) //11
println(f1()) //12
val f2 = foo2()
println(f2()) //11
}

def foo() = {
//a相当于外部变量
var a = 10
b: Int => a + b
}


def foo2() = {
var a = 10
()=>{a+=1;a}
}
}

/*
闭包:
一个函数访问了外部的局部变量,则这个函数和它访问的局部变量称为闭包
闭包会阻值外部局部变量的销毁
*/
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
class Outer{
private int ccc;

public void fun1(){
int a=1;

final int b = 2;
class Innor{
public void fun2(){
// System.out.println(a); error
System.out.println(b);
System.out.println(ccc);
}
}
//为什么在内部类中传递的参数(局部变量)必须是final
//不是final就是因为局部变量保存在栈中,栈弹出,变量就没有了
//声明为final就是常量
//主要还是看变量会不会出现生命周期不一致问题
//导致原因还是java没有闭包
new Thread(()->{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//如果不是final,是一个局部变量
//这里方法内的局部变量就不存在了
Innor innor = new Innor();
innor.fun2();
}).start();
}
}

class Outer2{
final int b =11;

class Innor2{
final int b=1;

public void fun(){
//就近原则 访问自己的b
System.out.println(b);
//访问外部类的b
System.out.println(Outer2.this.b);
}
}
}

05定义方法
https://jiajun.xyz/2020/11/02/scala/05定义方法/
作者
Lambda
发布于
2020年11月2日
更新于
2021年8月5日
许可协议