欢迎光临
我们一直在努力

Scala函数定义完全指南:从基础语法到高阶应用

Scala函数定义完全指南:从基础语法到高阶应用

    • 1. 引言:函数是一等公民
    • 2. 函数 vs 方法:首先理解概念
    • 3. 定义方法:使用 def 关键字
      • 3.1 基本语法
      • 3.2 最简单的函数
      • 3.3 带参数的函数
      • 3.4 多个参数
      • 3.5 无参函数的特殊规则
    • 4. 返回类型的指定规则
      • 4.1 必须指定返回类型的情况
      • 4.2 可以省略返回类型的情况
      • 4.3 特殊返回类型:Unit
      • 4.4 返回类型选择流程图
    • 5. 函数字面量:使用 => 定义函数
      • 5.1 基本语法
      • 5.2 函数赋值给变量
      • 5.3 多参数函数
      • 5.4 无参数函数
      • 5.5 方法的ETA展开
    • 6. 高阶函数:函数作为参数和返回值
      • 6.1 接受函数作为参数
      • 6.2 返回函数
      • 6.3 集合中的高阶函数
    • 7. 参数的高级特性
      • 7.1 默认参数值
      • 7.2 命名参数
      • 7.3 可变参数
    • 8. 选择指南:何时使用哪种方式?
      • 场景化建议
    • 9. 总结
      • 9.1 核心要点回顾
      • 9.2 返回类型指定原则
      • 9.3 最终建议

🌺The Begin🌺点点关注,收藏不迷路🌺

1. 引言:函数是一等公民

在Scala中,函数是一等公民。这意味着:

  • 你可以将函数赋值给变量
  • 可以将函数作为参数传递给其他函数
  • 可以从函数中返回函数

这种设计让Scala既是一门面向对象的语言,也是一门函数式编程语言。掌握函数的定义和使用,是进入Scala函数式编程大门的钥匙。

本文将系统介绍Scala中定义函数的各种方式,以及如何指定返回类型,并通过丰富的示例帮助你快速上手。

2. 函数 vs 方法:首先理解概念

在深入语法之前,我们需要先澄清一个重要的概念区别:

#mermaid-svg-x3x81oDKLKU3i8m5{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-x3x81oDKLKU3i8m5 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-x3x81oDKLKU3i8m5 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-x3x81oDKLKU3i8m5 .error-icon{fill:#552222;}#mermaid-svg-x3x81oDKLKU3i8m5 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-x3x81oDKLKU3i8m5 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-x3x81oDKLKU3i8m5 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-x3x81oDKLKU3i8m5 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-x3x81oDKLKU3i8m5 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-x3x81oDKLKU3i8m5 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-x3x81oDKLKU3i8m5 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-x3x81oDKLKU3i8m5 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-x3x81oDKLKU3i8m5 .marker.cross{stroke:#333333;}#mermaid-svg-x3x81oDKLKU3i8m5 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-x3x81oDKLKU3i8m5 p{margin:0;}#mermaid-svg-x3x81oDKLKU3i8m5 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-x3x81oDKLKU3i8m5 .cluster-label text{fill:#333;}#mermaid-svg-x3x81oDKLKU3i8m5 .cluster-label span{color:#333;}#mermaid-svg-x3x81oDKLKU3i8m5 .cluster-label span p{background-color:transparent;}#mermaid-svg-x3x81oDKLKU3i8m5 .label text,#mermaid-svg-x3x81oDKLKU3i8m5 span{fill:#333;color:#333;}#mermaid-svg-x3x81oDKLKU3i8m5 .node rect,#mermaid-svg-x3x81oDKLKU3i8m5 .node circle,#mermaid-svg-x3x81oDKLKU3i8m5 .node ellipse,#mermaid-svg-x3x81oDKLKU3i8m5 .node polygon,#mermaid-svg-x3x81oDKLKU3i8m5 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-x3x81oDKLKU3i8m5 .rough-node .label text,#mermaid-svg-x3x81oDKLKU3i8m5 .node .label text,#mermaid-svg-x3x81oDKLKU3i8m5 .image-shape .label,#mermaid-svg-x3x81oDKLKU3i8m5 .icon-shape .label{text-anchor:middle;}#mermaid-svg-x3x81oDKLKU3i8m5 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-x3x81oDKLKU3i8m5 .rough-node .label,#mermaid-svg-x3x81oDKLKU3i8m5 .node .label,#mermaid-svg-x3x81oDKLKU3i8m5 .image-shape .label,#mermaid-svg-x3x81oDKLKU3i8m5 .icon-shape .label{text-align:center;}#mermaid-svg-x3x81oDKLKU3i8m5 .node.clickable{cursor:pointer;}#mermaid-svg-x3x81oDKLKU3i8m5 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-x3x81oDKLKU3i8m5 .arrowheadPath{fill:#333333;}#mermaid-svg-x3x81oDKLKU3i8m5 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-x3x81oDKLKU3i8m5 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-x3x81oDKLKU3i8m5 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-x3x81oDKLKU3i8m5 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-x3x81oDKLKU3i8m5 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-x3x81oDKLKU3i8m5 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-x3x81oDKLKU3i8m5 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-x3x81oDKLKU3i8m5 .cluster text{fill:#333;}#mermaid-svg-x3x81oDKLKU3i8m5 .cluster span{color:#333;}#mermaid-svg-x3x81oDKLKU3i8m5 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-x3x81oDKLKU3i8m5 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-x3x81oDKLKU3i8m5 rect.text{fill:none;stroke-width:0;}#mermaid-svg-x3x81oDKLKU3i8m5 .icon-shape,#mermaid-svg-x3x81oDKLKU3i8m5 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-x3x81oDKLKU3i8m5 .icon-shape p,#mermaid-svg-x3x81oDKLKU3i8m5 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-x3x81oDKLKU3i8m5 .icon-shape .label rect,#mermaid-svg-x3x81oDKLKU3i8m5 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-x3x81oDKLKU3i8m5 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-x3x81oDKLKU3i8m5 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-x3x81oDKLKU3i8m5 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

Scala中的'函数'广义

方法def定义

函数字面量=>定义

属于类/对象有名称可被重写

独立对象可赋值给变量是FunctionN实例

核心区别:

  • 方法(Method):用def定义,属于某个对象或类,是面向对象的概念
  • 函数(Function):用=>定义,是一个独立的对象(FunctionN的实例),是函数式编程的概念

在实际开发中,我们通常混用这两个术语,但这个区别在理解Scala的高级特性时至关重要。

3. 定义方法:使用 def 关键字

3.1 基本语法

def 方法名(参数名: 参数类型): 返回类型 = {
// 方法体
// 最后一行表达式的值就是返回值
}

3.2 最简单的函数

// 无参数、无返回值(实际返回Unit)
def sayHello(): Unit = {
println("Hello, Scala!")
}

// 调用
sayHello()

3.3 带参数的函数

// 一个参数,返回String
def greet(name: String): String = {
return "Hello, " + name // 可以使用return,但不推荐
}

// 更Scala风格:省略return,最后一行就是返回值
def greetScalaStyle(name: String): String = {
"Hello, " + name // 没有return,没有分号
}

// 单表达式函数可以省略花括号
def conciseGreet(name: String): String = "Hello, " + name

3.4 多个参数

def add(x: Int, y: Int): Int = {
x + y
}

// 调用
val sum = add(5, 3) // 8

3.5 无参函数的特殊规则

如果函数没有参数,定义时可以省略括号:

// 定义时省略括号
def currentTime = System.currentTimeMillis()

// 调用时也不能加括号
println(currentTime) // 正确
// println(currentTime()) // 编译错误!

如果定义时加了括号,调用时可加可不加:

def currentTimeWithParens() = System.currentTimeMillis()

// 以下两种方式都正确
println(currentTimeWithParens())
println(currentTimeWithParens) // 也可以省略

4. 返回类型的指定规则

4.1 必须指定返回类型的情况

Scala编译器通常可以推断返回类型,但有些情况必须显式指定:

情况1:递归函数

// 递归函数必须指定返回类型
def factorial(n: Int): Int = {
if (n <= 1) 1
else n * factorial(n 1) // 编译器无法推断递归调用的类型
}

情况2:返回值类型模糊

// 可能返回不同类型,需要指定共同的父类型
def getValue(flag: Boolean): Any = {
if (flag) 42 // Int
else "hello" // String
} // Int和String的共同父类是Any

情况3:公开API

// 对外暴露的API,最好显式声明类型,形成文档
class Calculator {
def add(x: Int, y: Int): Int = x + y // 明确文档
}

4.2 可以省略返回类型的情况

// 简单函数,类型一目了然
def double(x: Int) = x * 2 // 编译器推断返回Int

// 单行函数
def square(x: Double) = x * x // 推断返回Double

// 私有方法,不影响对外接口
private def log(msg: String) = println(s"[LOG] $msg")

4.3 特殊返回类型:Unit

Unit相当于Java中的void,表示函数不返回有意义的值:

def logMessage(message: String): Unit = {
println(s"LOG: $message")
// 可以省略: Unit,因为返回值类型明确
}

// 省略写法
def logMessage(message: String) = println(s"LOG: $message")

4.4 返回类型选择流程图

#mermaid-svg-cHoCK0W2PyazAArd{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-cHoCK0W2PyazAArd .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-cHoCK0W2PyazAArd .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-cHoCK0W2PyazAArd .error-icon{fill:#552222;}#mermaid-svg-cHoCK0W2PyazAArd .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-cHoCK0W2PyazAArd .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-cHoCK0W2PyazAArd .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-cHoCK0W2PyazAArd .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-cHoCK0W2PyazAArd .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-cHoCK0W2PyazAArd .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-cHoCK0W2PyazAArd .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-cHoCK0W2PyazAArd .marker{fill:#333333;stroke:#333333;}#mermaid-svg-cHoCK0W2PyazAArd .marker.cross{stroke:#333333;}#mermaid-svg-cHoCK0W2PyazAArd svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-cHoCK0W2PyazAArd p{margin:0;}#mermaid-svg-cHoCK0W2PyazAArd .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-cHoCK0W2PyazAArd .cluster-label text{fill:#333;}#mermaid-svg-cHoCK0W2PyazAArd .cluster-label span{color:#333;}#mermaid-svg-cHoCK0W2PyazAArd .cluster-label span p{background-color:transparent;}#mermaid-svg-cHoCK0W2PyazAArd .label text,#mermaid-svg-cHoCK0W2PyazAArd span{fill:#333;color:#333;}#mermaid-svg-cHoCK0W2PyazAArd .node rect,#mermaid-svg-cHoCK0W2PyazAArd .node circle,#mermaid-svg-cHoCK0W2PyazAArd .node ellipse,#mermaid-svg-cHoCK0W2PyazAArd .node polygon,#mermaid-svg-cHoCK0W2PyazAArd .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-cHoCK0W2PyazAArd .rough-node .label text,#mermaid-svg-cHoCK0W2PyazAArd .node .label text,#mermaid-svg-cHoCK0W2PyazAArd .image-shape .label,#mermaid-svg-cHoCK0W2PyazAArd .icon-shape .label{text-anchor:middle;}#mermaid-svg-cHoCK0W2PyazAArd .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-cHoCK0W2PyazAArd .rough-node .label,#mermaid-svg-cHoCK0W2PyazAArd .node .label,#mermaid-svg-cHoCK0W2PyazAArd .image-shape .label,#mermaid-svg-cHoCK0W2PyazAArd .icon-shape .label{text-align:center;}#mermaid-svg-cHoCK0W2PyazAArd .node.clickable{cursor:pointer;}#mermaid-svg-cHoCK0W2PyazAArd .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-cHoCK0W2PyazAArd .arrowheadPath{fill:#333333;}#mermaid-svg-cHoCK0W2PyazAArd .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-cHoCK0W2PyazAArd .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-cHoCK0W2PyazAArd .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-cHoCK0W2PyazAArd .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-cHoCK0W2PyazAArd .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-cHoCK0W2PyazAArd .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-cHoCK0W2PyazAArd .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-cHoCK0W2PyazAArd .cluster text{fill:#333;}#mermaid-svg-cHoCK0W2PyazAArd .cluster span{color:#333;}#mermaid-svg-cHoCK0W2PyazAArd div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-cHoCK0W2PyazAArd .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-cHoCK0W2PyazAArd rect.text{fill:none;stroke-width:0;}#mermaid-svg-cHoCK0W2PyazAArd .icon-shape,#mermaid-svg-cHoCK0W2PyazAArd .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-cHoCK0W2PyazAArd .icon-shape p,#mermaid-svg-cHoCK0W2PyazAArd .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-cHoCK0W2PyazAArd .icon-shape .label rect,#mermaid-svg-cHoCK0W2PyazAArd .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-cHoCK0W2PyazAArd .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-cHoCK0W2PyazAArd .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-cHoCK0W2PyazAArd :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

定义函数

函数是否递归?

必须显式指定返回类型

返回值类型是否明确?

是公开API吗?

必须显式指定返回类型

建议显式指定

可以省略,让编译器推断

5. 函数字面量:使用 => 定义函数

5.1 基本语法

// 函数字面量的语法
(参数列表) => 函数体

5.2 函数赋值给变量

// 将函数字面量赋值给变量
val addOne: Int => Int = (x: Int) => x + 1

// 类型可以省略,让编译器推断
val addOne = (x: Int) => x + 1

// 调用
println(addOne(5)) // 6

5.3 多参数函数

// 多个参数用括号包围
val add: (Int, Int) => Int = (x, y) => x + y

// 更简洁的写法
val multiply = (x: Int, y: Int) => x * y

println(add(3, 4)) // 7
println(multiply(3, 4)) // 12

5.4 无参数函数

// 无参数的函数字面量
val getRandom = () => Math.random()

// 调用时必须加括号
println(getRandom())
println(getRandom()) // 每次调用返回不同的值

5.5 方法的ETA展开

当期望一个函数但传入一个方法时,Scala会自动将方法转换为函数(ETA展开):

def addMethod(x: Int, y: Int): Int = x + y

// 将方法赋值给函数变量
val addFunction = addMethod _ // 下划线将方法转换为函数

// 现在addFunction是一个函数
println(addFunction(5, 3)) // 8

6. 高阶函数:函数作为参数和返回值

6.1 接受函数作为参数

// 定义一个函数,接受另一个函数作为参数
def applyOperation(x: Int, y: Int, op: (Int, Int) => Int): Int = {
op(x, y)
}

// 使用
val result1 = applyOperation(5, 3, (a, b) => a + b) // 8
val result2 = applyOperation(5, 3, (a, b) => a * b) // 15

// 更简洁的写法:使用占位符
val result3 = applyOperation(5, 3, _ + _) // 8
val result4 = applyOperation(5, 3, _ * _) // 15

6.2 返回函数

// 定义一个函数,返回一个新的函数
def multiplier(factor: Int): Int => Int = {
(x: Int) => x * factor
}

// 使用
val double = multiplier(2)
val triple = multiplier(3)

println(double(5)) // 10
println(triple(5)) // 15

6.3 集合中的高阶函数

val numbers = List(1, 2, 3, 4, 5)

// map: 对每个元素应用函数
val doubled = numbers.map(_ * 2) // List(2, 4, 6, 8, 10)

// filter: 过滤元素
val evens = numbers.filter(_ % 2 == 0) // List(2, 4)

// reduce: 聚合操作
val sum = numbers.reduce(_ + _) // 15

// foreach: 遍历执行
numbers.foreach(println) // 打印每个数字

7. 参数的高级特性

7.1 默认参数值

def greet(name: String, title: String = "Mr."): String = {
s"$title $name"
}

println(greet("Smith")) // Mr. Smith
println(greet("Smith", "Dr.")) // Dr. Smith

7.2 命名参数

def createUser(name: String, age: Int, email: String = ""): User = {
User(name, age, email)
}

// 使用命名参数,可以打乱顺序,也可以只指定部分
val user1 = createUser(name = "Alice", age = 25)
val user2 = createUser(age = 30, name = "Bob", email = "bob@example.com")

7.3 可变参数

def sum(numbers: Int*): Int = {
numbers.sum
}

println(sum(1, 2, 3)) // 6
println(sum(1, 2, 3, 4, 5)) // 15

8. 选择指南:何时使用哪种方式?

#mermaid-svg-pzUFYXu39C6BeFwu{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-pzUFYXu39C6BeFwu .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-pzUFYXu39C6BeFwu .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-pzUFYXu39C6BeFwu .error-icon{fill:#552222;}#mermaid-svg-pzUFYXu39C6BeFwu .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-pzUFYXu39C6BeFwu .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-pzUFYXu39C6BeFwu .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-pzUFYXu39C6BeFwu .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-pzUFYXu39C6BeFwu .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-pzUFYXu39C6BeFwu .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-pzUFYXu39C6BeFwu .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-pzUFYXu39C6BeFwu .marker{fill:#333333;stroke:#333333;}#mermaid-svg-pzUFYXu39C6BeFwu .marker.cross{stroke:#333333;}#mermaid-svg-pzUFYXu39C6BeFwu svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-pzUFYXu39C6BeFwu p{margin:0;}#mermaid-svg-pzUFYXu39C6BeFwu .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-pzUFYXu39C6BeFwu .cluster-label text{fill:#333;}#mermaid-svg-pzUFYXu39C6BeFwu .cluster-label span{color:#333;}#mermaid-svg-pzUFYXu39C6BeFwu .cluster-label span p{background-color:transparent;}#mermaid-svg-pzUFYXu39C6BeFwu .label text,#mermaid-svg-pzUFYXu39C6BeFwu span{fill:#333;color:#333;}#mermaid-svg-pzUFYXu39C6BeFwu .node rect,#mermaid-svg-pzUFYXu39C6BeFwu .node circle,#mermaid-svg-pzUFYXu39C6BeFwu .node ellipse,#mermaid-svg-pzUFYXu39C6BeFwu .node polygon,#mermaid-svg-pzUFYXu39C6BeFwu .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-pzUFYXu39C6BeFwu .rough-node .label text,#mermaid-svg-pzUFYXu39C6BeFwu .node .label text,#mermaid-svg-pzUFYXu39C6BeFwu .image-shape .label,#mermaid-svg-pzUFYXu39C6BeFwu .icon-shape .label{text-anchor:middle;}#mermaid-svg-pzUFYXu39C6BeFwu .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-pzUFYXu39C6BeFwu .rough-node .label,#mermaid-svg-pzUFYXu39C6BeFwu .node .label,#mermaid-svg-pzUFYXu39C6BeFwu .image-shape .label,#mermaid-svg-pzUFYXu39C6BeFwu .icon-shape .label{text-align:center;}#mermaid-svg-pzUFYXu39C6BeFwu .node.clickable{cursor:pointer;}#mermaid-svg-pzUFYXu39C6BeFwu .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-pzUFYXu39C6BeFwu .arrowheadPath{fill:#333333;}#mermaid-svg-pzUFYXu39C6BeFwu .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-pzUFYXu39C6BeFwu .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-pzUFYXu39C6BeFwu .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-pzUFYXu39C6BeFwu .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-pzUFYXu39C6BeFwu .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-pzUFYXu39C6BeFwu .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-pzUFYXu39C6BeFwu .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-pzUFYXu39C6BeFwu .cluster text{fill:#333;}#mermaid-svg-pzUFYXu39C6BeFwu .cluster span{color:#333;}#mermaid-svg-pzUFYXu39C6BeFwu div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-pzUFYXu39C6BeFwu .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-pzUFYXu39C6BeFwu rect.text{fill:none;stroke-width:0;}#mermaid-svg-pzUFYXu39C6BeFwu .icon-shape,#mermaid-svg-pzUFYXu39C6BeFwu .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-pzUFYXu39C6BeFwu .icon-shape p,#mermaid-svg-pzUFYXu39C6BeFwu .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-pzUFYXu39C6BeFwu .icon-shape .label rect,#mermaid-svg-pzUFYXu39C6BeFwu .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-pzUFYXu39C6BeFwu .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-pzUFYXu39C6BeFwu .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-pzUFYXu39C6BeFwu :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

是,多处调用

否,临时使用

需要定义一段可执行逻辑

是否需要复用?

使用方法def

使用函数字面量

是否属于类的行为?

定义为类的方法

定义为单例对象的方法

作为参数传递?

定义匿名函数或占位符语法

赋值给val变量

场景化建议

场景推荐方式示例
类的方法 def def calculateTax(amount: Double): Double
工具函数 def in object object MathUtils { def square(x: Int) = x*x }
集合转换逻辑 匿名函数 list.map(_ * 2)
需要传递的行为 函数变量 val op: (Int,Int)=>Int = _ + _
递归函数 def + 显式类型 def factorial(n: Int): Int
回调函数 函数字面量 button.onClick(() => println("clicked"))

9. 总结

9.1 核心要点回顾

概念定义方式特点典型用途
方法 def 属于对象,可重载,支持默认参数 类的行为、API设计
函数字面量 => 独立对象,可作为值传递 高阶函数、回调
匿名函数 (参数) => 表达式 临时定义,无需命名 集合操作、事件处理

9.2 返回类型指定原则

  • 递归函数 → 必须显式指定
  • 公开API → 应该显式指定
  • 简单私有函数 → 可以省略
  • 返回值类型模糊 → 必须显式指定
  • 9.3 最终建议

    函数是Scala编程的核心,掌握各种定义方式能让你写出更简洁、更优雅的代码。记住两个黄金法则:

    • 用def定义可复用的方法
    • 用=>定义临时传递的函数

    随着实践的增加,你会自然而然地找到最适合特定场景的方式。

    在这里插入图片描述

    🌺The End🌺点点关注,收藏不迷路🌺

    赞(0)
    未经允许不得转载:171主机测评 » Scala函数定义完全指南:从基础语法到高阶应用
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址