This episode covers object-oriented programming in Groovy: classes, objects, properties, and constructors, then inheritance, traits, interfaces, and mixins. You will also be introduced to AST transformations and annotation-driven behavior that drastically reduce boilerplate.

Control flow and functions form program logic, but real applications are built from objects. Episode 5 takes you into Groovy's core paradigm: object-oriented programming that's more concise than Java.
You'll learn classes, objects, properties, constructors, inheritance, traits, interfaces, and an introduction to AST transformations. By the end of the episode, you can design clean domain models without Java boilerplate.
Groovy simplifies the JavaBean concept. Declaring a property without a visibility modifier automatically generates a getter and a setter:
class Pengguna {
String nama
int umur
}
def user = new Pengguna(nama: "Arman", umur: 25)
println user.nama
user.umur = 26
println user.umurdef user = new Pengguna(nama: "Arman", umur: 25) uses the named-argument constructor that Groovy creates automatically. Accessing user.nama calls the getter behind the scenes, and the assignment user.umur = 26 calls the setter.
Groovy still supports explicit constructors and methods as usual, but adds conveniences: methods can be called with or without parentheses, and return values are automatic.
class Kalkulator {
int tambah(int a, int b) {
return a + b
}
int kalikan(int a, int b) {
a * b
}
}
def k = new Kalkulator()
println k.tambah(2, 3)
println k.kalikan(4, 5)Note that kalikan omits return because the last expression's value is returned automatically. k.kalikan(4, 5) calls an instance method using the same pattern as Java.
Groovy supports single-class inheritance and implementing multiple interfaces, exactly like Java:
interface Menyapa {
String sapa()
}
class Makhluk {
String nama
}
class Manusia extends Makhluk implements Menyapa {
String sapa() {
"Halo, saya ${nama}"
}
}
def arman = new Manusia(nama: "Arman")
println arman.sapa()class Manusia extends Makhluk implements Menyapa shows the classic OOP hierarchy. new Manusia(nama: "Arman") again uses the named-argument constructor that automatically fills in the properties of the parent class.
Java interfaces couldn't carry default implementations before Java 8, and multiple inheritance isn't allowed. Groovy provides traits — code blocks that can be shared across many classes without multiple inheritance.
trait Berjalan {
void jalan() {
println "${this.getClass().getSimpleName()} sedang berjalan"
}
}
class Kucing implements Berjalan {
}
class Anjing implements Berjalan {
}
new Kucing().jalan()
new Anjing().jalan()trait Berjalan defines a jalan method with an implementation, and both classes use it without rewriting. new Kucing().jalan() proves that methods from a trait can be called directly.
A class can implement several traits at once, creating mixin behavior:
trait Berenang {
void berenang() {
println "Berenang"
}
}
class Ikan implements Berjalan, Berenang {
}class Ikan implements Berjalan, Berenang combines two traits in a single class. The combination Berjalan, Berenang is a form of composition that isn't possible with single inheritance.
AST transformations are a feature that modifies the syntax tree (Abstract Syntax Tree) at compile time, generating additional code automatically. Transformations are triggered by annotations such as @ToString, @EqualsAndHashCode, and @TupleConstructor.
With the @Canonical annotation, Groovy automatically generates toString, equals, hashCode, and a named-argument constructor:
import groovy.transform.Canonical
@Canonical
class Produk {
String nama
BigDecimal harga
}
def p = new Produk(nama: "Kopi", harga: 25000)
println p@Canonical generates all the boilerplate that would have to be written manually in Java. new Produk(nama: "Kopi", harga: 25000) builds the object with a named constructor, and println p displays a clean toString representation.
Some AST transformations frequently used in real projects:
@Builder for fluent builders.@TupleConstructor for position-based constructors.@Immutable for immutable objects.@CompileStatic to enable type checking at compile time.You'll use @CompileStatic in depth in episode 16 for performance, and other transformations are scattered throughout the series.
Episode 5 took you into Groovy's object-oriented paradigm: Groovy Beans with automatic getters and setters, standard inheritance and interfaces, traits for behavior composition, and AST transformations that eliminate boilerplate.
The key takeaways:
@Canonical generates toString, equals, and hashCode automatically.In episode 6 next, we'll discuss collections and the Groovy JDK — the Collection API for List, Map, and Set, closure-based iteration with each, collect, and findAll, as well as various Groovy enhancements for String, File, I/O, and Date.