Groovy 操作符重载:左移、右移等
Groovy 语言允许开发者为自定义类定义标准操作符(如 +, -, <<, >> 等)的行为。这种机制被称为“操作符重载”。本质上,每个操作符都对应着一个特定的方法名。当你在代码中使用某个操作符时,Groovy 编译器会自动将其转换为对该方法的调用。
理解操作符映射机制
Groovy 的操作符重载不需要像 Java 那样使用特殊的语法关键字,只需在类中实现对应名称的方法即可。当解释器遇到 a + b 时,它会在后台查找 a.plus(b) 方法。
查看下方表格,了解常用操作符与映射方法的关系。
| 操作符 | 方法名 | 描述 |
|---|---|---|
+ |
plus |
加法 |
- |
minus |
减法 |
* |
multiply |
乘法 |
/ |
div |
除法 |
** |
power |
幂运算 |
<< |
leftShift |
左移(常用于追加) |
>> |
rightShift |
右移(常用于弹出或移除) |
== |
equals |
相等比较 |
<=> |
compareTo |
比较大小(返回 -1, 0, 1) |
[] |
getAt |
获取索引处元素 |
[]= |
putAt |
设置索引处元素 |
使用左移操作符(<<)
左移操作符 << 在 Groovy 中最常用于“向集合中添加元素”或“向输出流写入数据”。
- 创建一个名为
LeftShiftDemo.groovy的文件。 - 输入以下代码,观察
leftShift方法如何实现元素追加功能。
class ShoppingCart {
def items = []
// 重载 << 操作符,映射到 leftShift 方法
ShoppingCart leftShift(String item) {
items << item
println "已添加商品: $item"
return this
}
void showCart() {
println "当前购物车: ${items}"
}
}
// 实例化对象
def cart = new ShoppingCart()
// 使用 << 操作符代替 addItem 方法
cart << "苹果" << "香蕉"
// 调用查看方法
cart.showCart()
- 运行该脚本。控制台将输出商品被添加的过程,最终显示包含“苹果”和“香蕉”的列表。
使用右移操作符(>>)
右移操作符 >> 常被设计为“弹出”或“移除”最后一个元素,或者将数据“导出”到某个目标。
- 创建一个名为
RightShiftDemo.groovy的文件。 - 定义
rightShift方法来移除并返回列表中的最后一个元素。
class Stack {
def elements = [10, 20, 30, 40]
// 重载 >> 操作符,映射到 rightShift 方法
def rightShift(File targetFile) {
def popped = elements.pop()
// 将弹出的元素写入文件
targetFile << "${popped}\n"
return popped
}
void showStack() {
println "栈内元素: ${elements}"
}
}
// 创建一个临时文件用于测试
def outFile = new File("output.txt")
if (outFile.exists()) outFile.delete()
def stack = new Stack()
// 使用 >> 操作符将数据弹出到文件
def val1 = stack >> outFile
println "弹出的值: $val1"
def val2 = stack >> outFile
println "弹出的值: $val2"
stack.showStack()
// 验证文件内容
println "文件内容: ${outFile.text}"
- 执行脚本。程序会使用
>>操作符将栈顶元素弹出并写入output.txt文件,同时打印出剩余的栈内元素。
重载算术与比较操作符
为了让自定义的对象支持加减乘除或大小比较,需要实现对应的算术和比较方法。
1. 算术操作符重载
假设我们需要处理“钱袋”对象,支持两个钱袋合并(+)。
- 新建
MoneyBag.groovy。 - 实现
plus方法。
class MoneyBag {
BigDecimal amount
MoneyBag(BigDecimal amount) {
this.amount = amount
}
// 重载 + 操作符
MoneyBag plus(MoneyBag other) {
return new MoneyBag(this.amount + other.amount)
}
@Override
String toString() {
return "Money: \$${amount}"
}
}
def bag1 = new MoneyBag(100.50)
def bag2 = new MoneyBag(200.75)
// 直接使用 + 号
def totalBag = bag1 + bag2
println "合并结果: $totalBag"
2. 比较操作符重载(<=>)
<=> 通常被称为“太空船操作符”。重载它可以让你的对象支持 >, <, >=, <= 等所有比较运算,并使对象可以被 Collections.sort 等方法排序。
- 新建
User.groovy。 - 实现
compareTo方法。该方法需返回int类型:负数表示小于,0 表示等于,正数表示大于。
class User implements Comparable<User> {
String name
int age
User(String name, int age) {
this.name = name
this.age = age
}
// 重载 <=> 操作符
@Override
int compareTo(User other) {
// 这里我们定义按年龄比较
return this.age <=> other.age
}
@Override
String toString() {
return "$name ($age)"
}
}
def u1 = new User("Alice", 30)
def u2 = new User("Bob", 25)
// 使用 > 符号(实际上调用的是 compareTo)
println "Alice 比 Bob 大吗? ${u1 > u2}"
// 排序测试
def users = [u1, u2, new User("Charlie", 35)]
users.sort()
println "按年龄排序后: ${users}"
- 运行代码。由于实现了
compareTo,Groovy 自动赋予了对象使用>进行判断的能力,并且sort()方法也能正确工作。
重载下标操作符([])
访问数组风格的语法 obj[index] 和 obj[index] = value 分别对应 getAt 和 putAt 方法。
- 新建
Matrix.groovy。 - 实现
getAt和putAt以模拟一个简单的矩阵访问。
class Matrix {
def data = [:]
// 重载 [] 读取操作符
def getAt(int key) {
return data.get(key, 0)
}
// 重载 []= 写入操作符
void putAt(int key, def value) {
data[key] = value
}
}
def matrix = new Matrix()
// 使用 [] 写入数据
matrix[1] = 100
matrix[5] = 500
// 使用 [] 读取数据
println "位置 1 的值: ${matrix[1]}"
println "位置 3 的值: ${matrix[3]}" // 默认返回 0
暂无评论,快来抢沙发吧!