8. What do you mean by polymorphism, inheritance, encapsulation, and dynamic binding?


Polymorphism – means the ability of a single variable of a given type to be used to reference objects of different types, and automatically call the method that is specific to the type of object the variable references. In a nutshell, polymorphism is a bottom-up method call. The benefit of polymorphism is that it is very easy to add new classes of derived objects without breaking the calling code (i.e. getTotArea() in the sample code shown below) that uses the polymorphic classes or interfaces. When you send a message to an object even though you don’t know what specific type it is, and the right thing happens, that’s called polymorphism. The process used by objectoriented
programming languages to implement polymorphism is called dynamic binding. Let us look at some sample code to demonstrate polymorphism:


Inheritance – is the inclusion of behaviour (i.e. methods) and state (i.e. variables) of a base class in a derived class so that they are accessible in that derived class. The key benefit of Inheritance is that it provides the formal mechanism for code reuse. Any shared piece of business logic can be moved from the derived class into the base class as part of refactoring process to improve maintainability of your code by avoiding code duplication. The existing class is called the superclass and the derived class is called the subclass. Inheritance can also be defined as the process whereby one object acquires characteristics from one or more other objects the same way children acquire characteristics from their parents.

There are two types of inheritances:

  1. Implementation inheritance (aka class inheritance): You can extend an applications’ functionality by reusing functionality in the parent class by inheriting all or some of the operations already implemented. In Java, you can only inherit from one superclass. Implementation inheritance promotes reusability but improper use of class inheritance can cause programming nightmares by breaking encapsulation and making future changes a problem. With implementation inheritance, the subclass becomes tightly coupled with the superclass. This will make the design fragile because if you want to change the superclass, you must know all the details of the subclasses to avoid breaking them. So when using implementation inheritance, make sure that the subclasses depend only on the behaviour of the superclass, not on the actual implementation. For example in the above diagram the
    subclasses should only be concerned about the behaviour known as area() but not how it is implemented.
  2. Interface inheritance (aka type inheritance): This is also known as subtyping. Interfaces provide a mechanism for specifying a relationship between otherwise unrelated classes, typically by specifying a set of common methods each implementing class must contain. Interface inheritance promotes the design concept of program to interfaces not to implementations. This also reduces the coupling or implementation dependencies between
    systems. In Java, you can implement any number of interfaces. This is more flexible than implementation inheritance because it won’t lock you into specific implementations which make subclasses difficult to maintain. So care should be taken not to break the implementing classes by modifying the interfaces.
Which one to use? Prefer interface inheritance to implementation inheritance because it promotes the design concept of coding to an interface and reduces coupling. Interface inheritance can achieve code reuse with the help of object composition. If you look at Gang of Four (GoF) design patterns, you can see that it favours interface inheritance to implementation inheritance.

Implementation inheritance

Interface inheritance

Let’s assume that savings account and term deposit account have a similar behavior in terms of depositing and withdrawing money, so we will get the super class to implement this behavior and get the subclasses to reuse

this behavior. But saving account and term deposit account have specific behavior in calculating the interest.


public abstract class Account {

public void deposit(double amount) {

//deposit logic

}


public void withdraw(double amount) {

//withdraw logic

}


public abstract double calculateInterest(double amount);

}


public class SavingsAccount extends Account {

public double calculateInterest(double amount) {

//calculate interest for SavingsAccount

}

}


public class TermDepositAccount extends Account {

public double calculateInterest(double amount) {

//calculate interest for TermDeposit

}

}


The calling code can be defined as follows for illustration

purpose only:


public class Test {

public static void main(String[] args) {

Account acc1 = new SavingsAccount();

acc1.deposit(5.0);

acc1.withdraw(2.0);

Account acc2 = new TermDepositAccount();

acc2.deposit(10.0);

acc2.withdraw(3.0);

acc1.calculateInterest(500.00);

acc2.calculateInterest(500.00);

}

}


Let’s look at an interface inheritance code sample, which makes

use of composition for reusability. In the following example the

methods deposit(…) and withdraw(…) share the same piece of code

in AccountHelper class. The method calculateInterest(…) has its

specific implementation in its own class.


public interface Account {

public abstract void deposit(double amount);

public abstract void withdraw(double amount);

public abstract int getAccountType();

}


public interface SavingsAccount extends Account{

public abstract double calculateInterest(double amount);

}


public interface TermDepositAccount extends Account{

public abstract double calculateInterest(double amount);

}


The classes SavingsAccountImpl, TermDepositAccountImpl

should implement the methods declared in its interfaces. The class

AccountHelper implements the methods deposit(…) and

withdraw(…)


public class SavingsAccountImpl implements SavingsAccount{

private int accountType = 1;

//helper class which promotes code reuse through composition

AccountHelper helper = new AccountHelper();

public void deposit(double amount) {

helper.deposit(amount, getAccountType());

}

public void withdraw(double amount) {

helper.withdraw(amount, getAccountType());

}

public double calculateInterest(double amount) {

//calculate interest for SavingsAccount

}

public int getAccountType(){

return accountType;

}

}


public class TermDepositAccountImpl implements

TermDepositAccount {

private int accountType = 2;

//helper class which promotes code reuse through composition

AccountHelper helper = new AccountHelper();

public void deposit(double amount) {

helper.deposit(amount, getAccountType());

}


public void withdraw(double amount) {

helper.withdraw(amount, getAccountType());

}

public double calculateInterest(double amount) {

//calculate interest for TermDeposit

}

public int getAccountType() {

return accountType;

}

}


The calling code can be defined as follows for illustration purpose

only:


public class Test {

public static void main(String[] args) {

Account acc1 = new SavingsAccountImpl();

acc1.deposit(5.0);

Account acc2 = new TermDepositAccountImpl();

acc2.deposit(10.0);

if (acc1.getAccountType() == 1) {

((SavingsAccount) acc1).calculateInterest(500.00);

}

if (acc2.getAccountType() == 2) {

((TermDepositAccount) acc2).calculateInterest(500.00);

}

}

}




Encapsulation – refers to keeping all the related members (variables and methods) together in an object. Specifying members as private can hide the variables and methods. Objects should hide their inner workings from the outside view. Good encapsulation improves code modularity by preventing objects interacting with each other in an unexpected way, which in turn makes future development and refactoring efforts easy.

Being able to encapsulate members of a class is important for security and integrity. We can protect variables from unacceptable values. The sample code below describes how encapsulation can be used to protect the MyMarks object from having negative values. Any modification to member variable “vmarks” can only be carried out through the setter method setMarks(int mark). This prevents the object “MyMarks” from having any negative values by throwing an exception.


5 comments:

  1. Join your scanner to the diagnostic data connection. How to entry
    diagnostics codes depends on the calendar year the Wrangler was manufactured.


    Here is my web blog www.99designforum.com

    ReplyDelete
  2. The most we reached was 5 PIDs of 17 accessible. Following we
    assessment the free of charge packages, we will review the compensated application plans.


    Feel free to surf to my webpage :: obd bluetooth **

    ReplyDelete
  3. Well connected to Major Expressway such as Pan-Island Expressway
    (PIE) and Central Expressway (CTE) to get you to places in no time.

    the interlace condo (http://theinterlacecondo.sg)

    ReplyDelete