What is Encapsulation ?
Variables in a class can be set to private and thus hidden from outside world or other classes. They can be accessed by using setter or getter methods that are public or protected to modify . see example below for better understanding
class NewHire{
private float salary; // --These private variables are hidden from outside classes --,getter and setter methods below are used for other classes to access them and this --is a good example of encapsulation and how data is hidden .
private float sickdays;
private float holidays;
public float getsalary() {
return salary;
}
public void setsalary(float salary) {
this.salary = salary;
}
public float getsickdays() {
return sickdays;
}
public void setsickdays(float sickdays) {
this.sickdays = sickdays;
}
public float getholidays() {
return holidays;
}
public void setholidays(float holidays) {
this.holidays = holidays;
}
}
public class EncapsulationTest {
public static void main(String[] args) {
NewHire h1 = new NewHire();
// using setters of NewHire
h1.setsickdays(5);
h1.setsalary(1500);
h1.setholidays(14);
// using getters of NewHire
System.out.println("Person has "+h1.getsalary()+" salary and hass "+h1.getsickdays()+" sickdays and number of holidays are "+h1.getholidays());
}
}
What is Inheritance ?
The objects of a class namely methods and variables can be inherited by another class as it’s own simply by using the keyword extends . A child class or sub class, can only inherit from one parent class also called super class . A parent class can however have multiple sub classes. All methods except those that are private are inherited by the child class. This can also be best explained with an example below.
/*Super class CARS is a parent of sub class ElectricCar below*/
public class Cars {
public int price;
public void testSpeed(){
System.out.println("Checking Speed...");
}
public void getColor(){
System.out.println("Getting color...");
}
// private method not visible to other classes
private void securecheck(){
System.out.println("This is confidential to Cars");
}
}
/** This class ElectricCar is a subclass and inherits from Cars */
public class ElectricCar extends Cars {
public String name;
public static void main(String[] args) {
ElectricCar venzaE = new ElectricCar();
venzaE.name = "Tes VenzaE"; // var of ElectricCar ie subclass
venzaE.price = 90500; // var of Cars ie Super Class
venzaE.playMusic(); // method see below of ElectricCar ie SubClass
venzaE.testSpeed(); // methods of Cars ie Super Class
venzaE.getColor();; // methods of Cars ie Super Class
}
public void playMusic(){
System.out.println("Playing Music Channel ");
}
}
What is Abstraction ?
Data Abstraction is the property by which complexities and non essential units are not displayed to user .It only shows the required or essential details . One may wonder the difference between data encapsulation and abstraction .A simplest way to explain would be encapsulation is “data hiding” where as data abstraction is “implementation hiding”. Encapsulation groups data and methods that act upon the data, data abstraction exposes the interface to the user and hides the details of implementation.
So what is an interface ? We saw earlier how inheritance allows a subclass to inherit from a super class .Java does not allow to inherit from more than one class. So to add additional functionality, we create what is called an interface. Interfaces are empty classes. They provide all of the methods you must use, but none of the code.Methods declared in an interface are by default abstract (only method signature, no body). They usually have an adjective name like “Drivable” below.
Example Interface Drivable
public interface Drivable {
double PI = 3.14159265; //fields in interface are final and cant change
int getWheels(); // All methods in an interface are public and abstract by default. An abstract method must be defined with implementation detail by any class that uses the interface.
void setWheels(int numWheels); // Methods are by default abstract ;It can not be final and abstract ; final means the method can't be changed and abstract means it must be changed hence cant be both!
double getSpeed();
void setSpeed(double speed);
}
Example Class Vehicle using the Interface Drivable and abstract class Crashable
/* For a class to use an interface we use the "implements" keyword. This class should have the methods implemented for each method defined in Drivable interface .You can have more than one interface.Now if you have another class say Crashable which is an abstract class and want to make it part of the abstract class use the "extends" keyword */
public class Vehicle extends Crashable implements Drivable {
int numOfWheels = 2;
double theSpeed = 0;
int carStrength = 0;
/* All methods must be as visible as those in the interface. If they are public in the interface they must be public in the subclass */
public int getWheels(){
return this.numOfWheels;
}
public void setWheels(int numWheels){
this.numOfWheels = numWheels;
}
public double getSpeed(){
return this.theSpeed;
}
public void setSpeed(double speed){
this.theSpeed = speed;
}
public Vehicle(int wheels, double speed){
this.numOfWheels = wheels;
this.theSpeed = speed;
}
public void setCarStrength(int carStrength){
this.carStrength = carStrength;
}
public int getCarStrength(){
return this.carStrength;
}
}
Example Abstract class Crashable used in class Vehicle with extends
/* If you want to create a class in which every method doesn't have to be implemented use abstract classes. Create an abstract class with the abstract keyword */
public abstract class Crashable{
boolean carDrivable = true;
public void youCrashed(){
this.carDrivable = false;
}
public abstract void setCarStrength(int carStrength);
public abstract int getCarStrength();
}
Example Main program calling all the above
public class LearnOOPInterfaceAbs {
public static void main(String[] args){
Vehicle car = new Vehicle(4, 100.0);
// Using methods from the interface Drivable
System.out.println("Cars Max Speed: "+car.getSpeed());
System.out.println("Cars Number of Wheels: "+car.getWheels());
// Using methods from abstract method Crashable
car.setCarStrength(10);
System.out.println("Car Strength: "+car.getCarStrength());
}
}
Summary:
- Interface : Drivable – defines methods and fields to be used no details
- Class: Vehicle – defines all methods ,fields with implementation
- Abstract Class : Crashable – defines methods not required to have details of implementation
- Main Program : Calls the Vehicle class by creating a new object and uses methods from Drivable interface and abstract methods from Crashable
- As we see the interface and abstract class hides the implementation details and only has what is necessary this is data abstraction.
- We can’t create instance(interface can’t be instantiated) of interface but we can make reference of it that refers to the Object of its implementing class.
- From Java 9 onwards, interfaces can contain static,private and static private methods but they cannot be inherited.
- Interfaces are used to implement abstraction. You may wonder why use interfaces when we have abstract classes? The reason is, abstract classes may contain non-final variables, whereas variables in interface are final, public and static.
What is Polymorphism ?
“Poly” means many and “morph” means forms .Basically it means to take on many forms. With inheritance and many multiple methods ,this can be really useful .There are two types of polymorphism static (or compile-time) and dynamic (or runtime) .
- In static polymorphism, methods can have the same name but different signatures . For eg. one of the methods may have 2 parameters and the other 3 OR one method may accept integers and other a double OR one method may accept strings and integers and other integers and strings, i.e they are in a different order(this is not usually used).It allows compiler to know which method has to be called and binds it to method call.
- In dynamic polymorphism ,the JVM determines the method to be executed at runtime .As we have already seen in inheritance , a sub class can override a method of its super class and establish its own behavior. The method names of both the super class and sub class may be same and even with the same parameters but provide different implementation.
SUPER CLASS
// Animal is as a Super class example
public class Animal {
private String name = "Animal";
public String favFood = "Food";
protected final void changeName(String newName){ // protected so other methods can call,final means it cant be changed by other classses
this.name = newName; //this is reference to object being created
}
protected final String getName(){
return this.name;}
public void eatStuff(){
System.out.println("My fav food " + favFood);}
public void walkAround(){
System.out.println(this.name + " walks around");}
public Animal(){}
public Animal(String name, String favFood){
this.changeName(name);
this.favFood = favFood;
}}
SUB CLASS
// Cat is a Subclass of Animal .You create subclasses with the extends keyword and Cat has all the Methods and Fields that Animal defined because Cat inherits all the methods and fields defined in Animal
public class Cat extends Animal{
public String favToy = "Yarn"; // adding new fields to the subclass
public void playWith(){ // You can add new methods
System.out.println("Yeah " + favToy);}
public void walkAround(){ // METHOD OVERRIDE EXAMPLE ----
System.out.println(this.getName() + " stalks around and then sleeps"); // this refers to a specific object created of type Cat }
public String getToy(){ return this.favToy;
}
public Cat(){ }
public Cat(String name, String favFood, String favToy){
super(name, favFood); // super calls the constructor for the super class Animal
this.favToy = favToy; // We set the favToy value in Cat because it doesn't
exist in the Animal class
} }
MAIN PROGRAM CALLING
public class LearnPolyMorphism{
public static void main(String[] args){ //Create Animal Object
Animal genericAnimal = new Animal();
System.out.println(genericAnimal.getName());
System.out.println(genericAnimal.favFood);
Cat morris = new Cat("Morris", "Tuna", "Rubber Mouse"); //create CAT class
// Print out the name, favFood and favToy
System.out.println(morris.getName());
System.out.println(morris.favFood);
System.out.println(morris.favToy);
// You can also create classes based on the super class
Animal tabby = new Cat("Tabby", "Salmon", "Ball");
// You pass objects like any other field
acceptAnimal(tabby);
}
public static void acceptAnimal(Animal randAnimal){
// Gets the name and favFood for the Animal passed
System.out.println(randAnimal.getName());
System.out.println(randAnimal.favFood);
// This is Polymorphism , interpreter automatically figures out what type of Animal it's dealing with and checks to make sure if methods were overwritten that they are called instead
randAnimal.walkAround();
// The interpreter won't find anything that doesn't originally exist in the Animal class however for example System.out.println(randAnimal.favToy); Throws an ERROR
// If you want access to fields or methods only found in the Cat class you have to cast the object to that specific class first
Cat tempCat = (Cat) randAnimal;
System.out.println(tempCat.favToy);
// You could also cast the object directly like this
System.out.println(((Cat) randAnimal).favToy);
// You can use instanceof to check what type of object you have. This results in a positive for Animal and for Cat
if (randAnimal instanceof Cat)
{
System.out.println(randAnimal.getName() + " is a Cat");
}
}
}