brighter green coffee background image, java coding symbol foreground

9.1 Java | Paradigm of Class Abstraction & Encapsulation

In this segment, I will talk about designing classes and show the various differences between Object Oriented & Procedural Programming.

Table of Contents

Abstracting & Encapsulating Classes

To make programming easier for programmers, classes are separated their implementation from how the classes are used or made to function. This is called Class abstraction.

The “fine-details” or “inner processes” of a class’s implementation are hidden from a user, because he does not need to know how the class is implemented. This is called Class encapsulation.

Let me give you an example that shows you how useful class encapsulation is. Let’s say that you made a circle object. Class encapsulation enables you to find the area of this circle object without knowing how the area is computed.

Another example is when you build a computer from parts you buy from online. You don’t need to know exactly how every single component works (class encapsulation). And you only need a general idea of what each part does so that you can put it together (class abstraction) i.e. motherboard connects everything, video card is responsible for the video, network card is responsible for connecting to the internet, cpu is the “brain” of the computer, etc.

So class abstraction is simplification of how a class is to be used. And class encapsulation is hiding the fine details of how a class works.

Loan Example

In this example we will be deconstructing loans to learn about class abstraction & encapsulation.

A loan can be seen as an object of the Loan class.

The data properties would consist of the interest rate, the amount loaned, the time period of the loan, etc.

The methods would be the process of computing the monthly and total payments for the loan.

So let’s say that you buy a car. A loan object is made from instantiating the Loan class. The Loan class is composed of the interest rate, the size of the loan, and the how long the loan lasts.

After that, you can use the methods to calculate the monthly and total payments for your loan. And you are not required to know the detail of how the methods works as a user of the Loan class.

Below I will be showing a program that calculates loan payments. Note that because the code for calculating the loan payments is in the main method, the program currently cannot reuse this code.

But defining the static methods for evaluating the monthly and total loan payments fixes the problem mentioned above.

But again, defining static methods is only a limited solution. It’s limitations show when you try to associate a date with the loan. Then you are forced to use objects to connect a date with a loan payment.

As you can see in Java, Object Oriented programming is focused on objects that are defined by actions and data inside the object. To contrast, Procedural programming is driven by actions which are separated from its data.

Loan Class Encapsulation via UML

So to tie together a date with a loan, you can make the loan class have the date and the loan’s properties in data fields. In this way, a loan object contains data and actions needed to process the data while at the same time integrating the loan data and actions into one object. With this in mind, here is how the UML diagram looks for the Loan class:

Loan The Class name -yearlyInterestRate: double loan's rate of interest (default is 2.5) -yearDuration: int # of years the loan lasts (default is 1) -loanSize: double The size of the loan (default is 1000 dollars) -loanTime: java.util.Date The date that the loan is made +Loan() Construct default Loan object +Loan(YearlyInterestRate: double, yearDuration: int, loanSize: double) Construct loan with specified rate, years, loan size +fetchYearlyInterestRate(): double Return the yearly interest rate of the loan. +fetchYearDuration(): int Return the number of years that the loan lasts +fetchLoanSize(): double return the size of the loan +fetchLoanTime(): java.util.Date return back the date the loan began +setYearlyInterestRate(YearlyInterestRate: double): void set the "new" yearly interest rate of the loan +setYearDuration(yearDuration: int): void set the "new" number of years that th loan lasts +setLoanSize(loanSize: double): void set the "new" size of the loan +fetchMonthlyPayment(): double Return the payment that is due each month of the loan +fetchTotalPayment(): double Return the payment that is due in total of the loan TheRevisionist.Org The + sign indicates a public modifier The - sign indicates a private modifier

Notice that we don’t know or see the code of the actual Loan class. But we can use a UML diagram to symbolize what is in the Loan class. In this way, we are “Encapsulating” the Loan class for the user.

Testing the Encapsulated Loan Class

The Loan class UML diagram right above can be used in place of the actual  Loan class code. The UML can be used in place of the Loan class code to develop a Java program that tests the Loan class, which you can see down below:

import java.util.Scanner;

public class TestLoanClass {
	//Main Method
	public static void main(String[] args) {
		// Make a Scanner Object
		Scanner input = new Scanner(System.in);
		
		// Enter the yearly interest rate
		System.out.print("Enter the yearly interest rate, for example, 8.25: ");
		double yearlyInterestRate = input.nextDouble();
		
		// Enter the number of years
		System.out.print ("Enter the number of years as an integer: ");
		int yearDuration = input.nextInt();
		
		// Enter the loan amount
		System.out.print("Enter the loan amount, for example, 120000.95: ");
		double loanSize = input.nextDouble();
		
		// Make the Loan object
		Loan loan = new Loan(yearlyInterestRate, yearDuration, loanSize);
		
		// Display loan date, monthly payment, and total payment
		System.out.printf("The loan was made on %s\n" + "The monthly payment is %.2f\nThe total payment is %.2f\n", loan.fetchLoanTime().toString(), loan.fetchMonthlyPayment(), loan.fetchTotalPayment());
	}
}

Output:

"C:\Program Files (x86)\Java\jdk1.8.0_91\bin\java" -Didea.launcher.port=7532 "-Didea.launcher.bin.path=C:\Program Files (x86)\JetBrains\IntelliJ IDEA 2016.1.3\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files (x86)\Java\jdk1.8.0_91\jre\lib\charsets.jar;C:\Program Files (x86)\Java\jdk1.8.0_91\jre\lib\deploy.jar;C:\Program Files (x86)\Java\jdk1.8.0_91\jre\lib\ext\access-bridge-32.jar;C:\Program Files (x86)\Java\jdk1.8.0_91\jre\lib\ext\cldrdata.jar;C:\Program Files (x86)\Java\jdk1.8.0_91\jre\lib\ext\dnsns.jar;C:\Program Files (x86)\Java\jdk1.8.0_91\jre\lib\ext\jaccess.jar;C:\Program Files (x86)\Java\jdk1.8.0_91\jre\lib\ext\jfxrt.jar;C:\Program Files (x86)\Java\jdk1.8.0_91\jre\lib\ext\localedata.jar;C:\Program Files (x86)\Java\jdk1.8.0_91\jre\lib\ext\nashorn.jar;C:\Program Files (x86)\Java\jdk1.8.0_91\jre\lib\ext\sunec.jar;C:\Program Files (x86)\Java\jdk1.8.0_91\jre\lib\ext\sunjce_provider.jar;C:\Program Files (x86)\Java\jdk1.8.0_91\jre\lib\ext\sunmscapi.jar;C:\Program Files (x86)\Java\jdk1.8.0_91\jre\lib\ext\sunpkcs11.jar;C:\Program Files (x86)\Java\jdk1.8.0_91\jre\lib\ext\zipfs.jar;C:\Program Files (x86)\Java\jdk1.8.0_91\jre\lib\javaws.jar;C:\Program Files (x86)\Java\jdk1.8.0_91\jre\lib\jce.jar;C:\Program Files (x86)\Java\jdk1.8.0_91\jre\lib\jfr.jar;C:\Program Files (x86)\Java\jdk1.8.0_91\jre\lib\jfxswt.jar;C:\Program Files (x86)\Java\jdk1.8.0_91\jre\lib\jsse.jar;C:\Program Files (x86)\Java\jdk1.8.0_91\jre\lib\management-agent.jar;C:\Program Files (x86)\Java\jdk1.8.0_91\jre\lib\plugin.jar;C:\Program Files (x86)\Java\jdk1.8.0_91\jre\lib\resources.jar;C:\Program Files (x86)\Java\jdk1.8.0_91\jre\lib\rt.jar;C:\Users\rock\IdeaProjects\Chapter 10\out\production\Chapter 10;C:\Program Files (x86)\JetBrains\IntelliJ IDEA 2016.1.3\lib\idea_rt.jar" com.intellij.rt.execution.application.AppMain TestLoanClass Enter the yearly interest rate, for example, 8.25: 1.00 Enter the number of years as an integer: 20 Enter the loan amount, for example, 120000.95: 10 The loan was made on Sat Jul 23 18:06:12 EDT 2016 The monthly payment is 0.05 The total payment is 11.04 Process finished with exit code 0

So you can see that the main method reads the interest rate, the duration of the payment, and the loan size. The main method also makes the Loan object, fetches the payment per month, and the total payment via the usage of the instance method in the Loan class.

Extra Notes:

  • printf allows you to format what you are printing out to the console.
  • The % character automatically substitutes with a value.
  • %.2f syntax tells Java to return your variable with 2 decimal places .2 in decimal representation of a floating-point number f from the start of the format specifier %.
  • The use of %s will result in the toString() method being called on the object.

Now down below I will show you the code that makes up the Loan class.

Revealing the Loan Class (un-encapsulated)

Above, I showed a UML diagram that acted to “encapsulate” or hide the Loan Class. Even though you didn’t see in detail what the Loan Class is, you are still able to test the Loan Class by using the UML. Down below, I will show you the “details” that I’ve previously encapsulated from the Loan Class.

public class Loan {
    private double yearlyInterestRate;
    private int yearDuration;
    private double loanSize;
    private java.util.Date loanTime;

    //The Default Constructor for the Loan Class
    public Loan() {
        this(2.5, 1, 1000);
    }

    // Construct a loan with a specified yearly interest rate, duration, and loan size

    public Loan(double yearlyInterestRate, int yearDuration, double loanSize) {
        this.yearlyInterestRate = yearlyInterestRate;
        this.yearDuration = yearDuration;
        this.loanSize = loanSize;
        loanTime = new java.util.Date();
    }

    // Return the Yearly Interest Rate
    public double fetchYearlyInterestRate() {
        return yearlyInterestRate;
    }

    // Return the duration of the loan
    public int fetchYearDuration() {
        return yearDuration;
    }

    // Return the size of the loan
    public double fetchLoanSize() {
        return loanSize;
    }

    // Return the time when the loan was taken
    public java.util.Date fetchLoanTime() {
        return loanTime;
    }

    // Set a yearly interest rate
    public void setYearlyInterestRate(double yearlyInterestRate) {
        this.yearlyInterestRate = yearlyInterestRate;
    }

    // Set the loan duration
    public void setYearDuration(int yearDuration) {
        this.yearDuration = yearDuration;
    }

    // Set the size of the loan
    public void setLoanSize(double loanSize) {
        this.loanSize = loanSize;
    }

    // Find and Calculate the monthly payment to return
    public double fetchMonthlyPayment() {
        double monthlyInterestRate = yearlyInterestRate / 1200;
        double monthlyPayment = loanSize * monthlyInterestRate / (1 - (1/ Math.pow(1 + monthlyInterestRate, yearDuration * 12)));
        return monthlyPayment;
    }

    // Find and Calculate the total payment
    public double fetchTotalPayment() {
        double totalPayment = fetchMonthlyPayment() * yearDuration * 12;
        return totalPayment;
    }
}

So I want to drive home a few points through this exercise. First, Java programmers has to design their programs/classes to be encapsulated and abstract, so that their team members can quickly understand what the program/class does and build upon it, and so that clients can use the Java application without much knowledge about how the program/class works and instead given a simple explanation that they can understand quickly.

To show the usefulness of class encapsulation & abstraction, let’s take into consideration the output of the testClassLoan.java program. Imagine that the client or user only sees is what is in the console; none of the code. The console asks the user to input the yearly interest rate, the number of years the loan lasts, and the size of the loan- which is easily understood by the client/user. After executing the program the client receives information on the current time that the loan was made and what the monthly & total payments are- all without needing to know what made the program work.

Let me finish by saying that the purpose of abstraction & encapsulation is to improve the usability and flexibility of a class or program.


◄◄◄BACK | NEXT►►►

What's Your Opinion?