Object-Oriented Concepts and Constructs

From Sinfronteras
Revision as of 19:51, 4 April 2018 by Adelo Vieira (talk | contribs) (Virtual Methods)
Jump to: navigation, search

Four fundamental OOP concepts

  • Encapsulation
  • Inheritance
  • Polymorphism
  • Abstraction

Encapsulation

Encapsulation in Java is a mechanism of wrapping the data (variables) and code acting on the data (methods) together as a single unit. In encapsulation the variables of a class will be hidden from other classes, and can be accessed only through the methods of their current class, therefore it is also known as data hiding.

To achieve encapsulation in Java:

  • Declare the variables of a class as private.
  • Provide public setter and getter methods to modify and view the variables values.
TestEncapsulation.java
public class TestEncapsulation{
    
    private String name;
    private String idNum;
    private int age;
   
    public int getAge(){
        return age;
    }
    
    public String getName(){
        return name;
    }
    
    public String getIdNum(){
        return idNum;
    }
    
    public void setAge(int newAge){
        age = newAge;
    }
    
    public void setName(String newName){
        name = newName;
    }
    
    public void setIdNum(String newId){
        idNum = newId;
    }
    
}

The public setXXX() and getXXX() methods are the access points of the instance variables of the TestEncapsulation class. Normally, these methods are referred as getters and setters. Therefore any class that wants to access the variables should access them through these getters and setters.

The variables of the EncapTest class can be accessed as below:

/* File name : RunEncapsulation.java */

public class RunEncapsulation{
    public static void main(String args[]){
        TestEncapsulation encap = new TestEncapsulation();
        encap.setName("James");
        encap.setAge(20);
        encap.setIdNum("12343ms");
        
        System.out.print("Name : " + encap.getName() + " Age : " + encap.getAge());
    }
}

This would produce the following result:

Name : James Age : 20

Benefits of Encapsulation:

  • The fields of a class can be made read-only or write-only.
  • A class can have total control over what is stored in its fields.
  • The users of a class do not know how the class stores its data. A class can change the data type of a field and users of the class do not need to change any of their code.

Inheritance

Inheritance can be defined as the process where one class acquires the properties (methods and fields) of another. With the use of inheritance the information is made manageable in a hierarchical order.

The class which inherits the properties of other is known as subclass (derived class, child class) and the class whose properties are inherited is known as superclass (base class, parent class).


extends keyword

extends is the keyword used to inherit the properties of a class. With use of the extends keyword the subclasses will be able to inherit all the properties of the superclass except for the private properties of the superclass.

Example:

class Super{
    ...
    ...
}


class Sub extends Super{
    ...
    ...
}
Calculation.java
package calculation;

class Calculation {
    int z;
    
    public void addition(int x, int y){
        z=x+y;
        System.out.println("The sum of the given numbers:"+z);
    }
    
    public void substraction(int x,int y){
        z=x-y;
        System.out.println("The difference between the given numbers:"+z);
    }
}
MyCalculation.java
package calculation;

public class MyCalculation extends Calculation{
    
    public void multiplication(int x, int y){
        z = x*y;
        System.out.println("The product of the given numbers is: "+z);
    }
    
    public static void main(String args[]){
        int a=20, b=10;
        MyCalculation demo = new MyCalculation();
        demo.addition(a,b);
        demo.substraction(a, b);
        demo.multiplication(a, b);
    }
}

Using extends keyword, My_Calculation inherits the methods addition() and Subtraction() from Calculation class.

You can instantiate the class as given below as well. But using the superclass reference variable ( cal in this case ) you cannot call the method multiplication(), which belongs to the subclass My_Calculation:

Calculation cal = new My_Calculation();
demo.addition(a, b);
demo.Subtraction(a, b);

A subclass inherits all the members (fields, methods, and nested classes) from its superclass. Constructors are not members, so they are not inherited by subclasses, but the constructor of the superclass can be invoked from the subclass.

The super keyword

The super keyword is similar to this keyword. The following are the scenarios where the super keyword is used.

  • It is used to differentiate the members of superclass from the members of subclass, if they have same names.
  • It is used to invoke the superclass constructor from subclass.
Differentiating the members

If a class is inheriting the properties of another class, and if the members of the superclass have the same names as the sub class, to differentiate these variables we use super keyword as shown below.

super.variable
super.method();


Sample Code

In the given program you have two classes namely Sub_class and Super_class, both have a method named display() with different implementations, and a variable named num with different values.


package btest2_the_super_keyword;

class Super_class{
    int num=20;

    //display method of superclass
    public void display(){
        System.out.println("This is the display method of superclass");
    }
}
package btest2_the_super_keyword;

public class Sub_class extends Super_class {
    int num=10;
    
    //display method of sub class
    public void display(){
        System.out.println("This is the display method of subclass");
    }
    
    public void my_method(){
        //Instantiating subclass
        Sub_class sub=new Sub_class();
        
        //Invoking the display() method of sub class
        sub.display();
        
        //Invoking the display() method of superclass
        super.display();
        
        //printing the value of variable num of subclass
        System.out.println("value of the variable named num in sub class:"+ sub.num);
        
        //printing the value of variable num of superclass
        System.out.println("value of the variable named num in super class:"+ super.num);
        
    }

    public static void main(String args[]){
        Sub_class obj = new Sub_class();
        obj.my_method();
    }
    
}
Invoking Superclass constructor

If a class is inheriting the properties of another class, the subclass automatically acquires the default constructor of the super class. But if you want to call a parameterized constructor of the super class, you need to use the super keyword as shown below.

super(values);
class SuperClass{
    
    int age;
    
    SuperClass(int age){
        this.age=age;
    }
    
    public void getAge(){
        System.out.println("The value of the variable named age in super class is: " +age);
    }
}
public class SubClass extends SuperClass {
    
    SubClass(int age){
        super(age);
    }
    
    public static void main(String argd[]){
        SubClass s = new SubClass(24);
        s.getAge();
    }
    
}

IS-A relationship

IS-A is a way of saying : This object is a type of that object.

public class Animal{

}

public class Mammal extends Animal{

}

public class Reptile extends Animal{

}

public class Dog extends Mammal{
    public static void main(String args[]){
        Animal a = new Animal();
        Mammal m = new Mammal();
        Dog    d = new Dog();

        System.out.println(m instanceof Animal); // true
        System.out.println(d instanceof Mammal); // true
        System.out.println(d instanceof Animal); // true
    }

}

The following are true:

  • Animal is the superclass of Mammal class.
  • Animal is the superclass of Reptile class.
  • Mammal and Reptile are subclasses of Animal class.
  • Dog is the subclass of both Mammal and Animal classes.

Now, if we consider the IS-A relationship, we can say:

  • Mammal IS-A Animal
  • Reptile IS-A Animal
  • Dog IS-A Mammal
  • Therefore : Dog IS-A Animal as well

HAS-A relationship

These relationships are mainly based on the usage. This determines whether a certain class HAS-A certain thing. This relationship helps to reduce duplication of code as well as bugs.

public class Vehicle{} 

public class Speed{} 

public class Van extends Vehicle{
    private Speed sp;
}

This shows that class Van HAS-A Speed. By having a separate class for Speed, we do not have to put the entire code that belongs to speed inside the Van class. We also can reuse the Speed class in multiple applications.

Types of inheritance

Types of inheritance

A very important fact to remember is that Java does not support multiple inheritance. This means that a class cannot extend more than one class. Therefore following is illegal:

public class extends Animal, Mammal{} // Illegal in Java

However, a class can implement one or more interfaces. This has made Java get rid of the impossibility of multiple inheritance.

Polymorphism

Polymorphism is the ability of an object to take on many forms. The most common use of polymorphism in OOP occurs when a parent class reference is used to refer to a child class object.

Any Java object that can pass more than one IS-A test is considered to be polymorphic. In Java, all Java objects are polymorphic since any object will pass the IS-A test for their own type and for the class Object.

It is important to know that the only possible way to access an object is through a reference variable. A reference variable can be of only one type. Once declared, the type of a reference variable cannot be changed.

The reference variable can be reassigned to other objects provided that it is not declared final. The type of the reference variable would determine the methods that it can invoke on the object.

Let us look at an example:

public interface Vegetarian{}

public class Animal{}

public class Deer extends Animal implements Vegetarian{}

The Deer class is considered to be polymorphic since this has multiple inheritance. The following are true for the above example:

  • A Deer IS-A Animal
  • A Deer IS-A Vegetarian
  • A Deer IS-A Deer
  • A Deer IS-A Object

When we apply the reference variable facts to a Deer object reference, the following declarations are legal:

Deer d = new Deer();

Animal a = d;

Vegetarian v = d;

Object o = d;

All the reference variables d,a,v,o refer to the same Deer object in the heap.

Virtual Methods

The behaviour of overridden methods in Java allows you to take advantage of polymorphism when designing your classes.

Method overriding, where a child class can override a method in its parent. An overridden method is essentially hidden in the parent class, and is not invoked unless the child class uses the super keyword within the overriding method.

package virtualmethods;

public class Employee {
    
    private String name;
    private String address;
    private int    number; 
    
    public Employee(String name, String address, int number) { 
        System.out.println("Constructing an Employee"); 
        this.name    = name; 
        this.address = address; 
        this.number  = number; 
    } 
    
    public void mailCheck() { 
        System.out.println("Mailing a check to "+ this.name + " "+ this.address);
    }
    
    public String toString() { 
        return name + " " + address + " " + number; 
    } 
    
    public String getName() { 
        return name; 
    } 
    
    public String getAddress() { 
        return address; 
    } 
    
    public void setAddress(String newAddress) {
        address = newAddress; 
    } 
    
    public int getNumber() {
        return number; 
    }
    
}
package virtualmethods;

public class Salary extends Employee {
    
    private double salary;
    
    public Salary(String name, String address, int number, double salary) { 
        super(name, address, number);
        setSalary(salary);
    } 
    
    public void mailCheck() {
        System.out.println("Within mailCheck of Salary class ");
        System.out.println("Mailing check to "+getName()+ " with salary "+salary);
    }
    
    public double getSalary() {
        return salary;
    }
    
    public void setSalary(double newSalary){
        if(newSalary >= 0.0){
            salary = newSalary;
        }
    }
    
    public double computePay(){
        System.out.println("Computing salary pay for " + getName());
        return salary/52;
    }
    
}
package virtualmethods;

public class VirtualDemo {
    public static void main(String [] args){
        
        Salary   s = new Salary("Joe Bloggs", "Dublin 10", 3, 3600.00);
        Employee e = new Salary("John Adams", "Dublin 12", 2, 2400.00);
        
        System.out.println("\nCall mailCheck using Salary reference:");        
        s.mailCheck();
        
        System.out.println("\nCall mailCheck using Employee reference:");
        e.mailCheck();
        
    }
    
}

This would produce the following result:

Constructing an Employee
Constructing an Employee

Call mailCheck using Salary reference:
Within mailCheck of Salary class 
Mailing check to Joe Bloggs with salary 3600.0

Call mailCheck using Employee reference:
Mailing a check to John Adams Dublin 12

Here, we instantiate two Salary objects . one using a Salary reference s, and the other using an Employee reference e. While invoking s.mailCheck() the compiler sees mailCheck() in the Salary class at compile time, and the JVM invokes mailCheck() in the Salary class at run time.

Invoking mailCheck() on e is quite different because e is an Employee reference. When the compiler sees e.mailCheck(), the compiler sees the mailCheck() method in the Employee class.

Here, at compile time, the compiler used mailCheck() in Employee to validate this statement. At run time, however, the JVM invokes mailCheck() in the Salary class.

This behavior is referred to as virtual method invocation, and the methods are referred to as virtual methods. All methods in Java behave in this manner, whereby an overridden method is invoked at run time, no matter what data type the reference is, which was used in the source code at compile time.

Abstraction

Prueba