75. Properties and Fields
In this chapter we’ll delve more into properties and fields. They’re almost the same thing and are known more generally as member variables as they hold data regarding the state of an object instance. In less technical terms, they help describe a specific instance (e.g. Jim) of a class (Person).
Properties
The class below is composed of three properties and could be used to pass a person’s details around in a system. You may come across references to this type of structure as “Groovy beans”:
class Person {
def name
def email
def mobile
}
def astrid = new Person()
astrid.name = 'Astrid Smithson'
astrid.email = 'astrid@example.com'
astrid.mobile = '0418 111 222'
println astrid.dump()
In the code above I create a new instance of the Person class by calling new Person() and can then access each property using dot-point notation. This type of class can be really handy when you just need a structure for storing and handing around data - say, for example, you load a record from a database and want to feed it to other classes and their methods for processing.
Groovy provides a built-in approach to passing in property values when creating a new instance. The code below creates a new Person but sets the property values using named arguments:
def astrid = new Person(name: 'Astrid Smithson', email: 'astrid@example.com', mo\
bile: '0418 111 222')
We don’t have to set all of the properties, just the ones we need:
def astrid = new Person(name: 'Astrid Smithson', email: 'astrid@example.com')
Viewing an object’s properties/fields
If you try to use println to display the details for astrid you’ll get something like Person@46423706. It’s not very useful - just the type of the Object and an identifier. If you want to find out the field values, call the dump method that all objects inherit from Object:
println astrid.dump()
Typed properties
Just as we saw with variables, properties can be defined with a specific data type, rather than with a dynamic type. The code below redefines the Person class with typed properties:
class Person {
String name
String email
String mobile
}
People often ask if they should just use def or assign an explicit type. My answer is pretty straight-forward: if you know how you’ll use it and you’ll only use it one way, give it a type. The name property is a good example and I would use String. In other situations you may want to be flexible in what you can store so use def.
Fields
A field is pretty much the same thing as a property - it’s a member variable - but there’s a difference: fields are defined with an access modifier and properties are not. An access modifier is used to allow/block access from other code using the class and its member variables and methods.
In the code below I have rewritten the Person class using fields rather than properties:
class Person {
public name
private email
private mobile
}
Firstly, you’ll see that I haven’t used the def keyword - I don’t need to do this when I provide an access modifier. I could have declared public def name but it’s not good style as the def is implied. We can specify a type for a field by stating the type after the access modifier:
class Person {
public String name
private String email
private String mobile
}
Default values
Properties and fields are much like variables and can be declared with an initial value:
class Person {
public String name = 'anonymous'
private String email = 'anon@example.com'
private String mobile = ''
}
The initial value doesn’t have to be a literal, it can be determined from an expression.
Casting maps to objects
Groovy gives bean-style objects a really interesting approach to casting1 a map or a list to an object. Let’s get an example going first:
class Person {
def name
def email
def mobile
}
def astrid = [name: 'Astrid Smithson', email: 'astrid@example.com'] as Person
println astrid.dump()
Person gretchen = [name: 'Gretchen Gaul', email: 'gretchen@example.com']
println gretchen.dump()
For the first person (astrid) I explicitly cast the map to a Person instance using
[name: 'Astrid Smithson', email: 'astrid@example.com'] as Person. Groovy creates a new instance of Person and calls
the name and email setters.
In the case of gretchen I don’t need to call as Person as Groovy infers this from the fact I declared the variable’s
type (Person gretchen).
- Remember the
asoperator?↩