Object Methods and Access
- Methods are the actions that an object can perform.
- They define the behaviour of an object and provide an interface for interacting with it.
In the Person class, methods like sleep, wakeUp, walk, and run define what a Person object can do.
class Person{
void sleep(){
...
}
void wakeUp(){
}
void walk(){
...
}
void run(){
}
}To utilise the benefits of OOP, we must clearly define the scope of class variables and methods, that is, specify from where they are directly accessible.
Hence, we need access modifiers.
Access modifiers
Keywords that define the visibility and accessibility of class members (variables and methods).
Access modifiers are essential for implementing encapsulation, a core principle of OOP that promotes data hiding and modular design.
We have three primary access modifiers:
Private
- Definition: Members marked as private are accessible only within the class that defines them.
- Purpose: Ensures that sensitive data and internal logic are protected from external modification.
- Java:
Here, in the ReadingMaterial class, instance variables like id, title, pages, and price are private.
class ReadingMaterial{
private int id;
private String title;
private int pages;
private double price;
public static void main(String[] args){ // to test
ReadingMaterial book = new ReadingMaterial(); // get book object
book.title = "Fahrenheit 451"; // error as you cannot access it from here
}
}The access modifier keyword is written before the data type in the declaration of the variable or method signature.
Protected
- Definition: Members marked as protected are accessible within the class, its subclasses, and classes in the same package.
- Purpose: Allows subclasses to inherit and use these members while keeping them hidden from unrelated classes.
The bookstoreName attribute in the ReadingMaterial class is protected.
class ReadingMaterial{
protected String bookstoreName;
...
}Protected access is particularly useful in inheritance hierarchies, where subclasses need to access certain members of their parent class.
Public
- Definition: Members marked as public are accessible from any class.
- Purpose: Provides an interface for interacting with the class's functionality.
Usually, classes are public.
public myClass{
...
}- Be cautious when making members public.
- Exposing too much can lead to unintended dependencies and make the codebase harder to maintain.
- Do not assume that members are public by default.
- When an access modifier is omitted, a member is accessible only within the same package.
- However, unlike protected, it will not be accessible to subclasses that are outside the package.
- Think of access modifiers as the locks on doors in a building.
- Private locks restrict access to specific rooms.
- Protected locks allow access to certain groups (like employees).
- Public areas are open to everyone.
Accessor Methods
Hence, to work with private and protected attributes, we need additional methods that provide access to manipulate such instance variables.
Getters
Methods used to retrieve the value of private attributes.
In other words, accessor methods, also known as getters, are used to retrieve the value of an object's instance variables without modifying them.
The getAge() method in the Person class is an accessor that returns the value of the age property.
public class Person{
private int age = 10; // private attribute, default 10
public int getAge(){ // getter
return this.age; // refer to instance variable
}
public static void main(String[] args){
Person myFriend = new Person();
// you cannot access myFriend.age directly
int friendAge = myFriend.getAge(); // hence, use getter instead
System.out.println(friendAge);
}
}
Accessor methods often have names starting with get, followed by the name of the variable they access.
Mutator Methods
Setters
Methods used to update the value of private attributes (in a controlled way).
In other words, mutator methods, also known as setters, are used to modify the value of an object's instance variables.
The setAge(int age) method in the Person class is a mutator that updates the age property.
public class Person{
private int age = 10; // private attribute, default 10
public int getAge(){ // getter
return this.age; // refer to instance variable
}
public void setAge(int ageIn){ // setter
// Here might go additional actions
this.age = ageIn; // refer to instance variable
}
public static void main(String[] args){
Person myFriend = new Person();
System.out.println("Initial value: "+ myFriend.getAge());
// you cannot access myFriend.age here
myFriend.setAge(20); // hence, use setter
System.out.println("New value: "+ myFriend.getAge());
}
}
Mutator methods typically start with set and include a parameter to specify the new value.
Constructors
Another method type that is of special interest in OOP is the constructor.
Constructors
Special methods used to initialise an object
Constructors are called only once when an object is instantiated.
Let's modify the Person class from before to include a constructor with one parameter.
public class Person{
private int age; // private attribute
public Person(int ageIn){ // constructor with parameter age
this.age = ageIn;
}
public int getAge(){ // getter
return this.age;
}
public void setAge(int ageIn){ // setter
this.age = ageIn;
}
public static void main(String[] args){
Person myFriend = new Person(10); // invoke constructor
System.out.println("Initial value: "+ myFriend.getAge());
}
}
Often it is useful to overload constructors for more flexibility.
Imagine coding a library system:
- Let’s start by defining a Book class for our library system.
- Each book will have attributes like a title (String), author (String), and availability (boolean) status.
- Additionally, we need to add:
- Encapsulation: The instance variables (title, author and isAvailable) are private, meaning they can only be accessed or modified through public methods.
- Accessors and mutators: The getTitle, getAuthor, and isAvailable methods allow controlled access to the private variables, while borrowBook and returnBook modify the state of the object.
- Constructor: The Book constructor initialises the object with a title and author, ensuring every book has these attributes when created.
public class Book {
// private attributes (encapsulation)
private String title;
private String author;
private boolean isAvailable = true; // available by default
public Book(String titleIn, String authorIn) { // constructor
this.title = titleIn;
this.author = authorIn;
}
// accessor methods (getters)
public String getTitle() {
return title;
}
public String getAuthor() {
return author;
}
public boolean isAvailable() {
return isAvailable;
}
// Mutator methods (borrow and return book)
public boolean borrowBook() {
if (isAvailable) {
this.isAvailable = false;
return true; // successfully borrowed
}
return false; // already borrowed
}
public void returnBook() {
this.isAvailable = true;
}
public static void main(String[] args){ // for testing
Book book1 = new Book("Fahrenheit 451", "Ray Bradbury");
// testing getters
System.out.println("Title: " + book1.getTitle());
System.out.println("Author: " + book1.getAuthor());
System.out.println("Available: " + book1.isAvailable());
// test borrowing the book
boolean borrowSuccess = book1.borrowBook();
System.out.println("Borrow attempt 1: " + borrowSuccess);
System.out.println("Available after borrow: " + book1.isAvailable());
// test borrowing unavailable
borrowSuccess = book1.borrowBook();
System.out.println("Borrow attempt 2: " + borrowSuccess);
// test returning the book
book1.returnBook();
System.out.println("Available after return: " + book1.isAvailable());
}
}
- What are the differences between private, protected, and public access modifiers?
- How do access modifiers support encapsulation in OOP?
- Why might you choose to use protected access for a class member?