Classes, Properties and Constructors

16.1 Classes and Properties

class Person {
    String name                  // property: private field + getName()/setName() generated
    int age
    final String id = UUID.randomUUID().toString()   // read-only property (getter only)
    private String secret        // explicitly private field (no accessors generated)
    protected String note
    static int count = 0

    String getDisplayName() { "$name ($age)" }        // custom getter → displayName property
    void setAge(int age) {                            // custom setter
        if (age < 0) throw new IllegalArgumentException("negative age")
        this.age = age
    }
    String toString() { "Person($name, $age)" }
}

def p = new Person(name: "Ana", age: 30)   // named-argument constructor (default constructor + setters)
println p.name                              // calls getName()
p.age = 31                                  // calls setAge()
println p.displayName
println p.@age                              // direct field access
println p.properties                        // map of properties
println p['name']                           // subscript property access
p.with { name = "Ana B."; age = 32 }

16.2 Constructors

Without explicit constructors, Groovy supports new X(prop: value, ...). Add @TupleConstructor, @MapConstructor, or @Canonical for more options (Module 24).

class Point {
    int x, y
    Point() { this(0, 0) }
    Point(int x, int y) { this.x = x; this.y = y }
}
def a = new Point(1, 2)
def b = [3, 4] as Point                    // list coercion calls the constructor
Point c = [5, 6]                           // implicit coercion on typed assignment
def d = new Point()

16.3 Static Members, Inner Classes and Initializers

class Registry {
    static final Map<String, Object> items = [:]
    static { println "static initializer" }
    { println "instance initializer" }
    static register(String k, v) { items[k] = v }
    class Inner { def outerItems() { items } }
    static class Nested {}
}
def anon = new Runnable() { void run() { println "anonymous inner class" } }

16.4 Object Equality and Hashing

== calls equals(). Implement equals and hashCode (or use @EqualsAndHashCode / @Canonical).

is() / === test reference identity.