U-Groovy
Sure! I see the source link, but I’ll need the actual text you’d like translated. Could you please paste the content you want me to translate into Simplified Chinese? Once I have it, I’ll keep the source line unchanged and preserve all formatting as you requested.
Source: …
概述
我已经在 Jenkins 流水线中使用 Groovy 工作了很长一段时间。
现在我正更多地转向 Java 领域,所以这是对这门语言能做什么进行简短总结的好时机。
在我看来,Groovy 是一种 U‑语言:未知、被低估且不被注意。很多人听说过它,但只有少数人真正了解它的便利性和通用性。
总体而言,Groovy 类似于 Java——它运行在 JVM 上并且能够理解纯 Java 代码,这让 Java 开发者可以立即上手使用。
与 Java 不同的是,Groovy 可以几乎在任何编程范式中使用,从而实现代码库的高度灵活结构。下面是几个简单的示例,展示了这种灵活性。
A. 命令式编程
命令式编程描述了程序 如何 逐步执行。它是编写计算机程序最常见的方式。
1. 脚本语言
Groovy 可以像 Bash 那样用作普通脚本语言:
println "this is just plain scripting"
a = 1
b = 2
println a + b
2. 动态类型的面向对象编程
你可以在面向对象风格下使用动态类型:
class Car {
def regNumber = "123AB"
def numberOfStarts = 0
def weight = 2
def start() {
numberOfStarts++
println "running"
}
def stop() {
println "stopping"
}
def getRegNumber() {
return regNumber
}
// Example of a dynamic getter (not required for the demo)
def getNumberOfStarts() {
return numberOfStarts
}
}
def car = new Car()
car.start()
car.start()
assert car.getNumberOfStarts() == 2
println car.getRegNumber()
car = "this is car"
println car
当静态类型显得大材小用时,你可以简化代码并避免使用它。
动态类型还意味着你可以将不同类型的值赋给同一个变量(def car)。方法可以根据运行时条件返回不同的类型。
3. 静态类型的面向对象编程
如果你更喜欢类似 Java 的风格,可以使用静态类型(注意这里没有分号):
class Plane {
String regNumber = "123AB"
int weight = 20
int numberOfFlights
void fly() {
numberOfFlights++
println "flying"
}
void land() {
println "landing"
}
String getRegNumber() {
return regNumber
}
int getNumberOfFlights() {
return numberOfFlights
}
}
Plane plane = new Plane()
plane.fly()
plane.fly()
assert plane.getNumberOfFlights() == 2
println plane.getRegNumber()
Source: …
B. 声明式编程
声明式编程描述应得到的结果是什么,而不是如何实现它。
1. 基于 Groovy 的声明式语法
你可以在 Groovy 中创建自定义的声明式 DSL(领域特定语言):
println "declarative programming"
def surroundedWithDashes(closure) {
println "-------------"
closure.call()
println "-------------"
}
def show(closure) {
println closure.call()
}
def sumOfNumbers = { a, b -> a + b }
surroundedWithDashes {
show { sumOfNumbers(3, 6) }
show { sumOfNumbers(1, 2) }
show { sumOfNumbers(5, 10) }
}
在 DSL 定义完成后,调用 surroundedWithDashes { … } 会自动生成所需的布局。
2. 函数式编程
Groovy 支持函数式编程概念,如 纯函数、函数链式调用、记忆化(memoization)和 柯里化(currying)。大多数任务只需使用三种方法即可表达:collect、findAll 和 inject。
println "functional programming"
def data = [1, 5, 8, 3, 5]
def result = data
.collect { it + 10 } // 为每个元素加 10
.findAll { it > 13 } // 只保留大于 13 的值
.toUnique() // 去除重复项
assert result == [15, 18]
优势不仅体现在链式调用,还体现在函数式特性上,例如:
- 记忆化 – 为给定输入缓存函数的结果。
- 柯里化 – 通过固定通用函数的部分参数来创建新函数。
Source: …
C. 元编程
元编程可以说是 Groovy 的标志性特性。它允许你在 编译时 或 运行时 修改或生成代码。
1. 编译时元编程
你可以使用 AST(抽象语法树)转换在编译期间生成代码:
println "compile-time metaprogramming"
@Log
class Car2 {
def regNumber
def numberOfStarts = 0
def weight = 2
@NullCheck
Car2(regNumber) {
this.regNumber = regNumber
}
def start() {
numberOfStarts++
log.info "log: running"
}
def stop() {
log.info "log: stopping"
}
String getRegNumber() {
return regNumber
}
}
try {
new Car2().start()
} catch (error) {
println "error was caught: ${error}"
}
new Car2("12345").start()
@Log 注入日志记录器,而 @NullCheck 为构造函数添加空值检查。源代码中不需要显式的空值检查代码。
2. 运行时元编程
在运行时,你可以拦截、注入,甚至合成方法和属性。这一能力使 Groovy 在构建 DSL、在测试中模拟对象或即时适配现有 API 时极其灵活。
示例
@Log
class Car3 {
def regNumber
def numberOfStarts = 0
def weight = 2
@NullCheck
Car3(regNumber) {
this.regNumber = regNumber
}
def start() {
numberOfStarts++
log.info "log: running"
}
def stop() {
log.info "log: stopping"
}
def getRegNumber() {
return regNumber
}
def methodMissing(String name, args) {
log.info "log: called missing method: ${name} with arguments: ${args}"
}
}
def car3 = new Car3("12345")
car3.someUnexistingMethod("with parameter")
car3.metaClass.additionalMethod = { param ->
log.info "log: called added method: additionalMethod with parameter: ${param}"
}
car3.additionalMethod("paramValue")
在实现了内置方法
methodMissing后,每当调用类的未定义方法时,都会执行该方法。
additionalMethod可以在运行时添加到类中,并成功使用。
为什么要使用此特性?
它在以下场景非常有用:
-
测试 – 尤其是需要 mock 时。
参见我的相关文章: Mocking with Groovy -
高级任务 – 如编写测试框架。
示例: GitHub 上的简化版 Jenkins 测试框架 – Jenkinson
要点
- Groovy 在 JVM 上运行,并且能够理解纯 Java 代码。
- 它支持 命令式、声明式、函数式和元编程 风格。
- 你可以选择 动态或静态类型(或两者混合)。
- 它的 DSL 构建 和 AST 转换 能力让你可以根据自己的领域定制语言。
无论你是在为 Jenkins 流水线编写快速脚本,还是在构建大型、类型安全的应用程序,Groovy 都提供了一个许多 Java 开发者忽视的多功能工具箱。祝编码愉快!
摘要
这些是编写 Groovy 代码的众多方式中的简单示例。我只触及了皮毛,但希望这些示例能激发对该语言的好奇心和兴趣。
我自己仍在学习 Groovy,但在一定程度上已经使用了这里展示的所有特性。完整的文档请参阅:
- Groovy 文档:
如果您还没有浏览过文档,强烈建议阅读——其中还有大量额外的语言特性。
在我看来,这种灵活性是选择 Groovy 作为任务或项目语言时最大的优势,同时它也是一个很好的教学工具。
希望这篇简短的文章对您有帮助。