ZetCode

Groovy 函数

最后修改于 2025 年 2 月 25 日

Groovy 中的函数是整洁、可重用的代码包,用于处理特定任务。它们可以简化您的程序,减少重复,并提高清晰度,使您的代码库易于导航。本教程通过实际操作示例,深入探讨了如何在 Groovy 中创建和应用函数。

定义函数

Groovy 函数以 def 关键字开始,后面跟着一个名称和可选参数,所有这些都包含在花括号中。它们是模块化、高效代码的构建块。

SimpleFunction.groovy
def welcomeUser(name) {
    "Welcome aboard, $name!"
}

println welcomeUser("Alice")

welcomeUser 函数接收一个 name 参数,并使用 Groovy 的字符串插值功能生成一个热情的问候语。想象一下在用户入职流程中,用个性化的方式问候新注册用户,简单而有效。

函数参数

函数可以处理多个参数,Groovy 还提供了默认值和命名参数等功能,使函数调用更加灵活和直观。

FunctionParameters.groovy
def greetUser(name, greeting = "Welcome") {
    "$greeting, $name!"
}

println greetUser("Alice")
println greetUser("Bob", "Hello")

greetUser 函数如果省略 greeting 参数,则默认为 "Welcome",让您可以动态调整问候语的语气。这可以用于通知系统,为不同的用户操作定制消息,而无需创建额外的函数。

返回值

函数通过 return 关键字返回值,但 Groovy 的简洁风格允许最后一个表达式自动作为返回值,无需额外操作。

ReturnValues.groovy
def calcSubtotal(items, price) {
    items * price
}

println calcSubtotal(3, 10.99)

calcSubtotal 函数将商品数量乘以价格,没有显式的 return 语句。可以将其想象成在线商店中计算购物车总价的功能,简洁、快速,并且可以根据需要添加更多逻辑。

函数重载

Groovy 跳过了传统的重载,而是依赖于默认参数和可选参数。这是一种无需复制代码签名即可处理各种输入值的绝佳方式。

FunctionOverloading.groovy
def logMessage(msg, level = "INFO", timestamp = false) {
    def prefix = timestamp ? "[${new Date()}] " : ""
    "$prefix[$level] $msg"
}

println logMessage("Login successful")
println logMessage("Error occurred", "ERROR")
println logMessage("Task started", "DEBUG", true)

logMessage 函数通过 leveltimestamp 的默认值来适应不同的日志级别,模仿了函数重载的效果。这可以作为应用程序的迷你日志记录器,能够从基本日志记录到详细日志记录,而无需重写代码,充分展现了 Groovy 的精妙之处。

高阶函数

Groovy 中的高阶函数可以接受或返回其他函数,从而解锁了动态、可重用的逻辑,就像瑞士军刀一样灵活地满足您的需求。

HigherOrderFunctions.groovy
def processData(data, transform) {
    transform(data)
}

def toUpper = { it.toUpperCase() }
def reverse = { it.reverse() }

println processData("hello", toUpper)
println processData("world", reverse)

processData 函数将一个 transform 闭包应用于 data。在这里,它可以将文本转换为大写或反转文本,非常适合文本编辑器的格式化工具,无需更改核心函数即可切换不同的转换方式。

递归函数

递归函数通过将问题分解成更小的部分来解决问题,它们是处理具有重复模式的任务的首选方法。

RecursiveFunction.groovy
def countDown(n) {
    if (n <= 0) return "Liftoff!"
    "$n... ${countDown(n - 1)}"
}

println countDown(3)

countDown 函数以递归方式从 n 计数到零,最后显示 "Liftoff!"。想象一下在发射倒计时应用程序中使用它,带有风格地倒计时,为递归增添了有趣的色彩。

闭包作为函数

Groovy 中的闭包可以作为函数使用,可以赋值给变量或在函数之间传递,模糊了命名函数和即时逻辑之间的界限。

ClosuresAsFunctions.groovy
def notify = { user -> "Notification sent to $user" }

println notify("Alice")

notify 是一个充当函数的闭包,用于发送模拟通知。这可以集成到消息队列中,以与命名函数相同的便利性传递警报,同时还具备闭包的灵活性。

函数组合

函数组合可以将多个函数组合成一个,使用 Groovy 的 <<>> 运算符将它们的效果链接起来,实现简洁、模块化的工作流程。

FunctionComposition.groovy
def trim = { it.trim() }
def cap = { it.capitalize() }
def cleanName = trim >> cap

println cleanName("  alice  ")

cleanName 函数结合了 trimcap 的功能,一次性清理姓名。可以考虑将其用于表单验证,逐步清理用户输入,而无需笨拙的中间调用。

带命名参数的函数

命名参数允许您以任何顺序使用参数调用函数,从而提高了复杂输入(如配置设置)的可读性。

NamedArgsFunction.groovy
def configServer(host, port = 8080, ssl = false) {
    "Server at $host:$port, SSL: $ssl"
}

println configServer(host: "localhost", ssl: true)

configServer 函数使用命名参数来清晰地设置服务器,并带有默认值。这适用于部署脚本,可以明确指定选项,而无需担心参数顺序。

使用列表处理的函数

函数可以使用 Groovy 的集合方法来处理列表,简化批量操作,如汇总数据。

ListFunction.groovy
def summarizeSales(sales) {
    def total = sales.sum()
    "Total sales: \$$total across ${sales.size()} items"
}

println summarizeSales([10.50, 22.75, 15.00])

summarizeSales 函数使用 sumsize 来汇总销售列表。这非常适合报告生成器,它在一个简洁的函数中提供了交易数据的快速快照。

记忆化函数

记忆化会缓存函数结果,通过重复的输入来加速函数调用,这是处理性能密集型任务的绝佳技巧。

MemoizedFunction.groovy
def fib = { n ->
    n <= 1 ? n : fib(n-1) + fib(n-2)
}.memoize()

println fib(10)

fib 函数计算斐波那契数列,并使用记忆化来避免冗余的递归。这可以优化数学工具,缓存结果以实现重复计算的快速响应。

使用函数的最佳实践

来源

Groovy 函数文档

本教程深入探讨了 Groovy 函数,展示了它们作为多功能、模块化代码块的作用。通过实际示例,我们看到了它们如何通过重用性、清晰度和诸如组合等巧妙技巧来增强您的程序。

作者

我叫 Jan Bodnar,是一名拥有多年编程经验的热情程序员。自 2007 年以来,我一直在撰写编程文章。到目前为止,我已撰写了 1400 多篇文章和 8 本电子书。我在编程教学方面拥有八年以上的经验。

列出 所有 Groovy 教程