![]() | Session 3 | ![]() |
Encapsulation
Encapsulation - hiding the implementation details of an object (internal state of an instance) from the clients of the object.
To encapsulate instance fields of an object, we declare them to be private by writing the keyword
private at the start of the declaration of each field, e.g.
// encapsulated instance fields private String breed; private int age;
Private fields are visible inside the class Dog (inside the Dog.java file), but not anywhere else. This means that we can no longer directly refer to instance fields from our client class.
To preserve the functionality of the client class, we need to provide methods for client class to access instance field values: the accessor methods (getters) and the mutator methods (setters).
If the value of an instance field is useful externally, it is common to write an accessor method into the object class to return that value into the client class. Here are accessors that provide access to the dog's breed and age fields:
// Returns the breed of the dog whose instance called the method
public String getBreed(){
return breed;
}
// Returns the age of the dog whose instance called the method
public int getAge(){
return age;
}
The client class that wishes to print a dog's breed and age values must be changed to the following:
// This code works with our encapsulated Dogs
System.out.println("Lisa is " + liza.getBreed() + ". She is " + liza.getAge() + " years old.");
It probably seems odd to use encapsulations and accessors. However, the accessor methods only return a copy of the field values (like breed and age) to the client class, but does not give the client any way to change it. In other words, these accessor methods give the client class the "read only" access to the state of the object.
Another benefit of encapsulation is that later we can change the internal structure of our object without having to modify our client code.
On the other hand, when the Dog class is encapsulated, one drawback is that it is no longer easy for the client class to set property values to an instance. This can be done creating mutator methods in the object class:
// Sets the breed and age of the dog whose instance called the method
public void setProperties(String breed, int age) {
this.breed = breed;
this.age = age;
}
Notice that now class Dog has some redundancy between its constructor and its method setProperties. The two bodies are essentially the same, setting the properties to an instance. The redundancy can be eliminated by having the constructor call setProperties rather than setting the field values manually. It is legal for an object to call its own instance methods from its constructor or other instance methods.
// Constructor
public Dog(String name, String breed, int age, String size, String color) {
setProperties(breed, age);
this.name = name;
this.size = "small";
this.color = color;
}
Last but not least, we can also generate getters and setters in a fast way using IntelliJ: in the Code menu choose Generate.
Self-assessment
![]() | Session 3 | ![]() |

