OOP: Encapsulation

​Object Oriented Programming has four major concepts, which are Encapsulation, Inheritance, Abstraction and Polymorphism. This article deals with the first concept Encapsulation. Consider this problem. The ABC book shop needs a software to maintain its billing procedures and stock management. This book shop sells books, magazines, newsletters and DVDs. The first step you need to do is developing a Book class to represent the books with the following attributes and behaviors. Remember that, attributes are represented by instance variables and the behaviors are represented by instance methods.
Attributes of Book
  • Title: String
  • Author: String
  • Price: double
Behaviors related to Book
  • Sell – void sell(int qty)
Now create a Book class, and then check it with the code below. Usually in my Java classes, students end up with this kind of Book class. (Implementation of sell method can be different.)
public class Book {
    // Title of the book.
    String title;
    // Author of the book.
    String author;
    // Price of the book.
    double price;

    /**
     * Print the total amount for given quantity.
     * @param qty The quantity
     */
    public void sell(int qty) {
        System.out.println("Total: $" + (qty * price));
    }
}
Assume that you are the developer of Book class and someone else in your team is going to use this Book class as shown below.
public class BookShop {
    public static void main(String[] args) {
        Book book = new Book();
        book.title = "Hamlet";
        book.author = "William Shakespeare";
        book.price = -5.95; // A negative price!

        System.out.println("Title: " + book.title);
        System.out.println("Price: $" + book.price);
        book.sell(2);
    }
}
A book with a negative price? This is such a ridiculous statement, even though it is technically valid. In an object oriented program, it should throw an exception at least print an error message (to satisfy those who do not know exceptions, because I teach Exceptions after OOP in my series of Java lectures). How to solve this problem? I accept that, we need to have an if-else condition, but where to have that if-else condition? We can write an if-else statement inside a code block only like methods. However, writing an if-else inside the main method is pointless as shown below.
public class BookShop {
    public static void main(String[] args) {
        Book book = new Book();
        book.title = "Hamlet";
        book.author = "William Shakespeare";
        if (-5.95 > 0) {
            book.price = -5.95;
        } else {
            System.out.println("Invalid price");
        }
        System.out.println("Title: " + book.title);
        System.out.println("Price: $" + book.price);
        book.sell(2);
    }
}
So…
We need an if-else block in the Book class; to add the if-else condition we need to add a method first. Look at this code now.
public class Book {
    String title;
    String author;
    double price;

    /**
     * Set the price.
     * @param price Price of the book.
     */
    public void setPrice(double price) {
        if (price > 0) {
            this.price = price;
        } else {
            System.out.println("Invalid price");
        }
    }

    public void sell(int qty) {
        System.out.println("Total: $" + (qty * price));
    }
}
But still the crazy developer can assign a negative price like this.
public class BookShop {
    public static void main(String[] args) {
        Book book = new Book();
        book.title = "Hamlet";
        book.author = "William Shakespeare";
        // Still directly assigning the value.
        // I am a rule breaker.
        book.price = -5.95;

        System.out.println("Title: " + book.title);
        System.out.println("Price: $" + book.price);
        book.sell(2);
    }
}
Even though we have added a safeguard, still we need to depend on this type of crazy developers to use the method we have defined. Can’t we restrict the developers to use the setPrice method only, not to directly assign any values?
There is a way; let’s define the price variable as a private variable. That seems to be fine, because no one can access a private variable directly. Only choice the developers have is using the setPrice method. Wait, then how can they read it back? To get the value assigned to the book, we need to provide another method – getPrice(). Now the Book class is:
public class Book {
    String title;
    String author;
    // private variable
    private double price;

    /**
     * Set the price.
     * @param price Price of the book.
     */
    public void setPrice(double price) {
        if (price > 0) {
            this.price = price;
        } else {
            System.out.println("Invalid price");
        }
    }

    /**
     * Get the price.
     * @return Price of the book.
     */
    public double getPrice() {
        return this.price;
    }

    public void sell(int qty) {
        System.out.println("Total: $" + (qty * price));
    }
}
and the BookShop class is:
public class BookShop {
    public static void main(String[] args) {
        Book book = new Book();
        book.title = "Hamlet";
        book.author = "William Shakespeare";
        book.setPrice(-5.95);   // Error message
        book.setPrice(5.95);

        System.out.println("Title: " + book.title);
        // System.out.println("Price: $" + book.price);
        System.out.println("Price: $" + book.getPrice());
        book.sell(2);
    }
}
Welcome To Encapsulation
Technically, Encapsulation is defining private variables and provide public getter and setter methods to access them. Conceptually Encapsulation is the technique of hiding implementation form the users. Now you have encapsulated the property “price” of the Book class. As you have seen, encapsulation allows you to define any desired rules and conditions. You can restrict the input, as well as you can return a formatted output. For example, in the getPrice method you can round off the price to two decimals and return it. Using encapsulation, you can create read only or write only properties, by providing either get or set method only. Encapsulated classes, let you to easily modify the code without affecting other classes.

Let’s finalize the code by encapsulating all the properties of Book class. Mark all the properties using private access modifier and create public getter and setter methods for those variables as shown here.
public class Book {
    private String title;
    private String author;
    private double price;

    public String getTitle() {
        return this.title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getAuthor() {
        return this.author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public void setPrice(double price) {
        if (price > 0) {
            this.price = price;
        } else {
            System.out.println("Invalid price");
        }
    }

    public double getPrice() {
        return this.price;
    }

    public void sell(int qty) {
        System.out.println("Total: $" + (qty * price));
    }
}
Naming Convention
Is it necessary to use get and set prefixes or can we use any method names? Technically you can use any names, but using get and set properties is the standard recommended for programmers. (In JavaEE environment, JavaBeans must use the get and set prefixes to ensure the compatibility with application servers and other frameworks.) Suppose if the property is a boolean for the getter method you can use either get or is. From this point onwards, strictly follow the getter and setter naming standard.

Sample Problem
In the Object Oriented Programming tutorial, a VeterinaryDoctor program is used to explain the bad design. (Click here to view the source code.) Encapsulate all the possible properties using private access modifier and provide public getter and setter methods. Modify the VeterinaryDoctor doctor class and the main method according to the changes you make.

To compare your solution click on this link.


Find the source codes at Git Hub.

The complete Object Oriented Programming article series are available here:
Object Oriented Programming:
            Encapsulation
            Inheritance
            Polymorphism
            Abstraction
Previous
Next Post »

Contact Form

Name

Email *

Message *