Encapsulation
Recall from the 'Java and Android' book, you learnt how to create objects and initialize its instance variables. Here is the example repeated for convenience:
public class BookStore {
public static void main(String[] args) {
Book book1 = new Book();
book1.title = "Harry Potter and the Sorcerer's Stone";
book1.author = "J.K. Rowling";
book1.price = 29;
System.out.println(book1.title);
}
}
class Book {
String title;
String author;
double price;
}
Although the above initialization of variables work, it is not a recommended way for initialization. You want to encapsulate the instance variables and give methods to set (initialize) the values and get (retrieve) the values.
Encapsulation helps keep the data safe from being manipulated from other classes. You see, the data for title, author and price variables belongs to the Book class and hence you should provide a method in Book class which can be used to change the values for these variables. Without encapsulation, any other class can directly access the data kept inside any object by using the dot operator, like the way it is done in the previous example. So let us fix the code:
public class BookStore {
public static void main(String[] args) {
Book book1 = new Book();
book1.setTitle("Harry Potter and the Sorcerer's Stone");
book1.setAuthor("J.K. Rowling");
book1.setPrice(29);
System.out.println(book1.getTitle());
Book book2 = new Book();
book2.setTitle("Harry Potter and the Prisoner of Azkaban");
book2.setAuthor("J.K. Rowling");
book2.setPrice(31);
System.out.println(book2.getTitle());
}
}
class Book {
private String title;
private String author;
private double price;
public void setTitle(String title) {
this.title = title;
}
public void setAuthor(String author) {
this.author = author;
}
public void setPrice(double price) {
this.price = price;
}
public String getTitle() {
return this.title;
}
public String getAuthor() {
return this.author;
}
public double getPrice() {
return this.price;
}
}
this keyword used in the above example, refers to the current object which is being invoked. this is used with the dot operator to refer to instance variables, methods and constructors of the given object. You will learn on constructors shortly.
Steps in encapsulation
Declare all variables of a class private. Using private modifier ensures that only the methods of that object alone can modify the variables.
Add setter methods which can be used to set the variable values.
Add getter methods which can be used to retrieve the variable values.
Both getter and setter methods are optional. If you do not want any other object to either set or get the data that is kept inside an object, you do not need to give these methods. Also, you can add more statements in the methods to either validate or manipulate the given value before setting/getting the variable. This is the real reason behind encapsulation.
- Getter methods are also called as Accessor methods. As they only return a value and not change the object state.
- Setter methods are also called as Mutator methods as they modify the state of the object.
Since we invoke the method which represents action on a specific object instance, you should no longer use static keyword while declaring methods which are meant for OOP usage.
What is method overloading?
Method overloading is a feature that allows a class to have more than one method having the same name, but with different arguments list.
class MyMath {
public static void main(String[] args) {
int a = calculate(5,6);
int b = calculate(5,6,"subtract");
System.out.println(a);
System.out.println(b);
}
public static int calculate(int a, int b) {
return a+b;
}
public static int calculate(int a, int b, String method) {
switch (method) {
case "add":
return a+b;
case "subtract":
return a-b;
}
return 0;
}
}
In the above class, you see two methods with the same name calculate. However, the parameters list is different. First calculate method takes two integer parameters and the second method takes two integer parameters and one string parameter.
Rules for overloading
- The return type of the overloaded methods should be the same
- Overloaded methods cannot have the same method signature. This is the fundamental principle of overloading
Aggregation (HAS-A relationship)
Aggregation is relationship between two classes. When one class references another then we say that first class HAS-A second class inside it. This is called aggregation. You have already seen aggregation in earlier examples. If you see the BookStore in the above code, you will see that BookStore class instantiates Book class inside its main method. Aggregation helps us to modularize code into separate entities.
Let us take another example. Let us assume you want to model a school in Java. You would start with defining the following classes: School, Teacher, Student and let us say you also want to represent address of each of these entities. Then you would define an Address class. Here is one hypothetical example
class Address {
private String streetAddress;
private String zipcode;
private String city;
private String country;
// setter and getter method go here. Not shown to keep code simple
}
class School {
private String name;
private Address address;
}
class Student {
private String name;
private Address address;
private String grade;
private String age;
private String gender;
}
class Teacher {
private String name;
private Address address;
private String subject;
}
In the above hypothetical example, Address object is referenced by School, Student and Teacher. The instances of all of them need another object which keeps the address information. In other words, instance of Student object HAS-A Address object, instance of Teacher object HAS-A Address object and finally instance of School object HAS-A Address object. You can get to a specific address object by first using the reference to the object which is holding it. This is called Aggregation. This is most of the time a one-way association. In the above example, you cannot get the reference of the School, Teacher or Student instances by having an Address instance. But the other way around is possible.