目录
-
- [第十一章 操作符](#第十一章 操作符)
-
- [1- 标识符](#1- 标识符)
- [2- 中置操作符](#2- 中置操作符)
- [3- 一元操作符](#3- 一元操作符)
- [4- 赋值操作符](#4- 赋值操作符)
- [5- 操作符的优先级](#5- 操作符的优先级)
- [6- 结合性](#6- 结合性)
- [7- apply和update方法](#7- apply和update方法)
- [8- 提取器](#8- 提取器)
- end
第十一章 操作符
在Scala中, 操作符是用来执行特定操作的符号或符号组合 ;
Scala允许开发人员自定义操作符, 这些操作符可以是字母、数字、符号或符号组合 ;
1- 标识符
在Scala中, 标识符是用来命名变量、方法、类等程序元素的名称 ;
标识符可以包含字母、数字、下划线和连字符, 但必须以字母或下划线开头 ;
标识符中的字母可以是大写或小写字母, Scala是区分大小写的 ;
标识符还可以使用Unicode字符, 但通常建议使用ASCII字符以确保代码的可读性 ;
标识规则:
- 标识符可以包含字母、数字、下划线和连字符, 但不能包含其他特殊字符 ;
- 标识符不能使用Scala的保留关键字, 如
val
、var
、class
等作为标识符 ; - 标识符可以是任意长度, 但建议使用有意义且描述性强的名称 ;
- 标识符通常使用驼峰命名法, 即首字母小写, 后续单词首字母大写, 例如:
myVariableName
; - 对于常量标识符, 通常使用全大写字母和下划线分隔, 例如:
MAX_SIZE
; - 避免使用单个字符作为标识符, 除非在循环变量或临时变量等简短作用域内使用 ;
在编写Scala代码时, 选择清晰、简洁和有意义的标识符是很重要的, 这有助于提高代码的可读性和可维护性 .
2- 中置操作符
在Scala中, 中置操作符是指位于两个操作数之间的操作符, 通常以中缀形式表示 ;
这些操作符可以是自定义的, 也可以是内置的 ;
中置操作符的使用, 使代码更具可读性和简洁性 ;
示例:
scala
// 定义一个类, 包含自定义的中置操作符
class ComplexNumber(val real: Double, val imaginary: Double) {
def +(other: ComplexNumber): ComplexNumber = {
new ComplexNumber(real + other.real, imaginary + other.imaginary)
}
def -(other: ComplexNumber): ComplexNumber = {
new ComplexNumber(real - other.real, imaginary - other.imaginary)
}
def *(other: ComplexNumber): ComplexNumber = {
new ComplexNumber(real * other.real - imaginary * other.imaginary,
real * other.imaginary + imaginary * other.real)
}
}
// 创建两个复数对象
val c1 = new ComplexNumber(2, 3)
val c2 = new ComplexNumber(1, 4)
// 使用自定义的中置操作符 + - *
val sum = c1 + c2 // 等同于 c1.+(c2) = new ComplexNumber(2 + 1, 3 + 4)
val difference = c1 - c2 // 等同于 c1.-(c2) = new ComplexNumber(2 - 1, 3 - 4)
val product = c1 * c2 // 等同于 c1.*(c2) = new ComplexNumber(2 * 1 - 3 * 4, 2 * 4 + 3 * 1)
println(s"Sum: ${sum.real} + ${sum.imaginary}i") // 输出: Sum: 3.0 + 7.0i
println(s"Difference: ${difference.real} + ${difference.imaginary}i") // 输出: Difference: 1.0 + -1.0i
println(s"Product: ${product.real} + ${product.imaginary}i") // 输出: Product: -10.0 + 11.0i
- 在上面的示例中,
ComplexNumber
类定义了自定义的中置操作符+
、-
和*
, 这些操作允许对复数进行加法和减法运算 ; - 通过使用中置操作符, 可以更直观的表示操作的含义, 使代码更易于理解 ;
3- 一元操作符
在Scala中, 一元操作符是作用于单个操作数的操作符 ;
Scala支持一元操作符的使用, 包括前缀一元操作符和后缀一元操作符 ;
示例:
-
前缀一元操作符: 前缀一元操作符位于操作数之前, 用于对操作数进行一元操作 ;
scala// 定义一个类, 包含前缀一元操作符 class Number(val value: Int) { def unary_+(): Number = new Number(+value) } // 创建一个Number对象 val num = new Number(10) // 使用前缀一元操作符 + val positiveNum = +num // 等同于 num.unary_+ println(positiveNum.value) // 输出: 10
-
后缀一元操作符: 后缀一元操作符位于操作数之后, 用于对操作数进行一元操作 ;
scala// 定义一个类, 包含后缀一元操作符 class BooleanWrapper(val value: Boolean) { def unary_!(): Boolean = !value } // 创建一个BooleanWrapper对象 val bool = new BooleanWrapper(true) // 使用后缀一元操作符 ! val notBool = !bool // 等同于 bool.unary_! println(notBool) // 输出: false
- 通过使用一元操作符, 可以对单个操作数进行简洁和直观的操作 ;
- 在Scala中, 开发人员可以自定义一元操作符来实现特定的功能, 增强代码的可读性和表达性 ;
4- 赋值操作符
在Scala中, 赋值操作符是用来给变量赋值的特殊操作符 ;
Scala中的赋值操作符通常以等号 (=) 结尾, 用于将右侧的值赋值给左侧的变量 ;
示例:
-
基本赋值操作符: 最基本的赋值操作符是等号 (=) , 用于将一个值赋值给一个变量 ;
scalavar x: Int = 10 // 将10赋给定义变量x println(x) // 输出: 10
-
复合赋值操作符 : Scala还是支持复合赋值操作符, 如
+=
、-=
、*=
等, 用于赋值的同时进行运算 ;scalavar y: Int = 20 y += 3 // 等价于y = y + 3 println(y) // 输出: 23
-
赋值操作符方法 : 在Scala中, 赋值操作符实际上是方法调用的简化形式, 例如
x += 1
实际上是x.+=(1)
的简写 ;scalavar z: Int = 30 z *= 2 // 等价于z = z * 2 println(z) // 输出: 60
- 通过使用赋值操作符, 可以方便地对变量进行赋值和运算操作 ;
- 在Scala中, 赋值操作符是编写代码是经常使用的重要元素之一 ;
5- 操作符的优先级
在Scala中, 操作符的优先级是根据他们的特性和用法来确定的 ;
通常, Scala中的操作符优先级遵循类似数学运算中的优先级规则, 例如 乘法优先于加法 ;
一下是优先级顺序(从高到低) :
- 一元操作符 (例如前缀和后缀一元操作符)
- 算术操作符 (例如乘法
*
、除法/
、取模%
) - 加法和减法操作符
- 位操作符 (例如按位与
&
、按位或|
) - 关系操作符 (例如 大于
>
、小于<
、等于==
) - 逻辑操作符 (例如 逻辑与
&&
、 逻辑或||
) - 赋值操作符 (例如 赋值
=
、+=
、-=
) - 其它特殊操作符 (例如 范围操作符
to
、until
)
在Scala中, 可以使用括号来明确指定操作符的优先级, 以确保表达式的求值顺序符合预期 ;
了解和遵循操作符的优先级规则有助于编写清晰和准确的代码 .
6- 结合性
在Scala中, 操作符的结合性是指子啊表达式中相同优先级的操作符出现时, 确定操作符的计算顺序 ;
Scala中的操作符结合性分为左结合和右结合性 ;
-
左结合性: 对于左结合性的操作符, 表达式中相同优先级的操作符从左向计算 ; 大多数操作符 (如加法、减法) 都是左结合的 ;
scala// 左结合性 val result = 1 + 2 + 3 // 从左向右计算: 1 + 2 = 3, 3 + 3 = 6 println(result) // Output: 6
-
右结合性: 对于右结合性的操作符, 表达式中相同优先级的操作符从右向左计算 ; 在Scala中, 以冒号结尾的操作符通常是右结合的 ;
scala// 右结合性 val list = 1 :: 2 :: 3 :: Nil // 从右向左计算: 1 :: (2 :: (3 :: Nil)) = List(1, 2, 3) println(list) // Output: List(1, 2, 3)
了解操作符的结合性有助于正确理解和编写表达式, 确保表达式按照预期的方式计算 ;
在Scala中, 可以通过查看操作符的定义或参考文档来确定操作符的结合性 .
7- apply和update方法
在Scala中, apply
和 update
方法是特殊的方法, 用于实现对象的函数调用和更新操作 ;
-
apply方法:
-
apply
方法允许对象函数一样被调用 . 当在对象后面加上圆括号并传入参数时, Scala会自动调用该对象的apply
方法 ; -
通过定义
apply
方法, 可以使对象具有函数的行为, 从而简化对象的使用 ; -
示例:
scalaclass MyFunction { def apply(x: Int): Int = x * 2 } val MyFunc = new MyFunction() val result = MyFunc(5) // 调用apply方法, 等同于调用 myFunc.apply(5) println(result) // 输出: 10
-
-
update方法:
-
update
方法用于更新对象的值, 类似于数字或映射的索引赋值操作 ; -
当使用
obj(key) = value
的语法时, Scala会自动调用对象的update
方法 ; -
示例:
scalaclass MyMap { private var map = Map[String, Int]() def update(key: String, value: Int): Unit = { map += (key -> value) } def apply(key: String): Int = map(key) } val myMap = new MyMap() myMap("key1") = 10 // 等同于调用 myMap.update("key1", 10) val retrievedValue = myMap("key1") // 等同于调用 myMap.apply("key1") println(retrievedValue) // 输出: 10
-
- 通过理解和使用
apply
和update
方法, 可以使对象在使用时更具灵活性和表现力, 同时提供类似函数调用和索引赋值的便利性 .
8- 提取器
在Scala中, 提取器 (Extractor) 是一种特殊的对象, 用于从输入中提取出特定模型的部分 ;
提取器通常与模型匹配结合使用, 允许从复杂数据结构中提取所需信息 ;
提取器通常包含两个主要方法: unapply
和 apply
;
unapply
方法用于从输入中提取值, 并返回一个Option
类型的结果 . 它通常用于模式匹配中的结构操作 ;apply
方法用于根据给定的参数创建对象的实例, 它通常用于构造对象 ;
示例:
scala
// 定义一个 Person 类
class Person(val name: String, val age: Int)
// 创建一个 Person 提取器对象
object Person {
def unapply(person: Person): Option[(String, Int)] = Some((person.name, person.age))
}
// 使用模式匹配和提取器
val person = new Person("John", 30)
person match {
case Person(name, age) => println(s"Name: $name, Age: $age") // 输出: Name: John, Age: 30
case _ => println("Match failed!")
}
- 在上面的示例中,
Person
对象作为提取器,unapply
方法用于从Person
对象中提取name
和age
, 以便在模式匹配中使用 ; - 通过使用提取器, Scala程序可以更灵活地处理复杂数据结构, 并实现模式匹配的功能 .