Classes - pford68/groovy-examples GitHub Wiki
Contents
- Syntax
- Fields
- Properties
- Constructors
- Scripts vs. Classes
- Inner Classes
- Interfaces
- Objects
- Notes
- References
- Related
Syntax
- Declared just like Java
- Omitting the access modifier gives the class public visibility.
Fields
A field is a member of a class or a trait which has:
- a mandatory access modifier (public, protected, or private)
- one or more optional modifiers (static, final, synchronized)
- an optional type (though omitting the type is considered bad practice)
- a mandatory name
A field may be initialized directly at declaration:
class Data {
private String id = IDGenerator.next()
// ...
}
Properties
A property is an externally visible feature of a class. Rather than just using a public field to represent such features (which provides a more limited abstraction and would restrict refactoring possibilities), the typical convention in Java is to follow JavaBean conventions, i.e. represent the property using a combination of a private backing field and getters/setters. Groovy follows these same conventions but provides a simpler approach to defining the property. You can define a property with:
- an absent access modifier (no public, protected or private)
- one or more optional modifiers (static, final, synchronized)
- an optional type
- a mandatory name
Groovy will then generate the getters/setters appropriately. For example:
class Person {
String name
int age
}
- creates a backing private String name field, a getName and a setName method
- creates a backing private int age field, a getAge and a setAge method
If a property is declared final, no setter is generated:
class Person {
final String name
final int age
Person(String name, int age) {
this.name = name
this.age = age
}
}
- defines a read-only property of type String
- defines a read-only property of type int
- assigns the name parameter to the name field
- assigns the age parameter to the age field
Properties are accessed by name and will call the getter or setter transparently, unless the code is in the class which defines the property:1
class Person {
String name
void name(String name) {
//this.name will directly access the field because the property
//is accessed from within the class that defines it
this.name = "Wonder$name"
}
String wonder() {
this.name //As in name() above, read access is done directly on the name field
}
}
def p = new Person()
p.name = 'Marge' // write access to the property is done outside of the Person class so it will implicitly call setName
assert p.name == 'Marge' // read access to the property is done outside of the Person class so it will implicitly call getName
p.name('Marge') // `this` will call the name method on Person which performs a direct access to the field
assert p.wonder() == 'WonderMarge' // this will call the wonder method on Person which performs a direct read access to the field
Properties do not require a backing field
By convention, Groovy will recognize properties even if there is no backing field provided there are getters or setters that follow the Java Beans specification. For example:
class PseudoProperties {
// a pseudo property "name"
void setName(String name) {}
String getName() {}
// a pseudo read-only property "age"
int getAge() { 42 }
// a pseudo write-only property "groovy"
void setGroovy(boolean groovy) { }
}
def p = new PseudoProperties()
p.name = 'Foo' // writing p.name is allowed because there is a pseudo-property name
assert p.age == 42 // reading p.age is allowed because there is a pseudo-readonly property age
p.groovy = true // writing p.groovy is allowed because there is a pseudo-writeonly property groovy
This syntactic sugar is at the core of many DSLs written in Groovy.
Listing Class Properties
It is possible to list the properties of a class thanks to the meta properties field of an instance:
class Person {
String name
int age
}
def p = new Person()
assert p.properties.keySet().containsAll(['name','age'])
Constructors
- Can be overloaded.
- Formal parameters do not need types.
- Can be called either with positional or named parameters2
Default Constructors
if you do not create a constructor (i.e., you use the default constructor), you always can invoke the default constructor with named parameters, which map instance properties to actual parameters:
class PersonWOConstructor {
String name
Integer age
}
// The default constructor for the class above can be invoked in any of the following ways:
def person4 = new PersonWOConstructor()
def person5 = new PersonWOConstructor(name: 'Marie')
def person6 = new PersonWOConstructor(age: 1)
def person7 = new PersonWOConstructor(name: 'Marie', age: 2)
This saves you from having to overload the constructor many times to support the different parameter lists.
Declared Constructors
Declared constructors use positional parameters. However, Lists can be coerced into creating instances, when declared constructors exist3:
class PersonConstructor {
String name
Integer age
PersonConstructor(name, age) {
this.name = name
this.age = age
}
}
def person1 = new PersonConstructor('Marie', 1)
def person2 = ['Marie', 2] as PersonConstructor
PersonConstructor person3 = ['Marie', 3]
Scripts vs. Classes
Groovy supports both scripts and classes.
A class like this:
// Main.groovy
Main.groovy
class Main {
static void main(String... args) {
println 'Groovy world!'
}
}
...can be written instead like this:
println 'Groovy world!'
- A script is always compiled into a class. The Groovy compiler will compile the class for you, with the body of the script copied into a run method.4
- If the script is in a file, then the base name of the file is used to determine the name of the generated script class. For example, if the name of the file is Main.groovy, then the script class is going to be Main.
- Variables in a script do not require a type defination.
// This is legal, and equivalent to using "int" to declare the variables. x = 1 y = 2 assert x+y == 3 - Scripts can have methods/functions.
- Methods and functions can be mixed with immediate code.
Inner Classes
See http://groovy-lang.org/objectorientation.html
Interfaces
See http://groovy-lang.org/objectorientation.html
Objects
The with method
Objects have a with() method like you see in other languages. While in JavaScript its use is discouraged for security/safety reasons, it is very much encouraged in Groovy.5 The with() method provides a concise syntax for performing multiple operations on the same object--that is, for invoking accessing methods and properties on the same object.
Example without with():
Below we are accessing properties and methods of the same object and having to repeat the object reference (e.g., server) each time.
server.name = application.name
server.status = status
server.sessionCount = 3
server.start()
server.stop()
Same example with with():
The with() block simply eliminates the need to repeat the object reference in each line.
server.with {
name = application.name
status = status
sessionCount = 3
start()
stop()
}
Notes
-
It is worth noting that this behavior of accessing the backing field directly is done in order to prevent a stack overflow when using the property access syntax within a class that defines the property.
-
http://groovy-lang.org/objectorientation.html#_constructors
In Groovy there are two ways to invoke constructors: with positional parameters or named parameters. The former one is like we invoke Java constructors, while the second way allows one to specify the parameter names when invoking the constructor.
-
http://groovy-lang.org/objectorientation.html#_constructors
There is [sic] three forms of using a declared constructor. The first one is the normal Java way, with the new keyword. The others rely on coercion of lists into the desired types. In this case, it is possible to coerce with the as keyword and by statically typing the variable.
-
The script
println 'Groovy world!'is equivalent to this:import org.codehaus.groovy.runtime.InvokerHelper class Main extends Script { def run() { println 'Groovy world!' } static void main(String[] args) { InvokerHelper.runScript(Main, args) } } -
http://groovy-lang.org/style-guide.html#_using_with_for_repeated_operations_on_the_same_bean
References
- http://groovy-lang.org/objectorientation.html
- http://groovy-lang.org/style-guide.html#_initializing_beans_with_named_parameters_and_the_default_constructor
- http://javarevisited.blogspot.com/2016/09/10-basic-differences-between-java-and-groovy-programming.html#ixzz4qyfYiBvZ
- http://groovy-lang.org/structure.html#_scripts_versus_classes