Foundations of Object Oriented Programming Part-1

Software Evolution

Software Evolution is a term which refers to the process of developing software initially, then timely updating it for various reasons, i.e., to add new features or to remove obsolete functionalities etc. Initially for designing small and simple programs, the machine language was used. Next came the Assembly Language which was used for designing larger programs. Both machine and Assembly languages are machine dependent. Next came Procedural Programming Approach which enabled us to write larger and hundred lines of code. Then in 1970, a new programming approach called Structured Programming Approach was developed for designing medium sized programs. In 1980's the size of programs kept increasing so a new approach known as OOP was invented.

image.png

Monolithic Programming Approach: In this approach, the program consists of sequence of statements that modify data. All the statements of the program are Global throughout the whole program. The program control is achieved through the use of jumps i.e. goto statements. In this approach, code is duplicated each time because there is no support for the function. Data is not fully protected as it can be accessed from any portion of the program. So this approach is useful for designing small and simple programs. The programming languages like ASSEMBLY and BASIC follow this approach.

Procedural Programming Approach: This approach is top down approach. In this approach, a program is divided into functions that perform a specific task. Data is global and all the functions can access the global data. Program flow control is achieved through function calls and goto statements. This approach avoids repetition of code which is the main drawback of Monolithic Approach. The basic drawback of Procedural Programming Approach is that data is not secured because data is global and can be accessed by any function. This approach is mainly used for medium sized applications. The programming languages: FORTRAN and COBOL follow this approach.

Structured Programming Approach: The basic principal of structured programming approach is to divide a program in functions and modules. The use of modules and functions makes the program more comprehensible (understandable). It helps to write cleaner code and helps to maintain control over each function. This approach gives importance to functions rather than data. It focuses on the development of large software applications. The programming languages: PASCAL and C follow this approach.

Object Oriented Programming Approach: The OOP approach came into existence to remove the drawback of conventional approaches. The basic principal of the OOP approach is to combine both data and functions so that both can operate into a single unit. Such a unit is called an Object. This approach secures data also. Now a days this approach is used mostly in applications. The programming languages: C++ and JAVA follow this approach. Using this approach we can write any lengthy code.

Introduction to Procedural

Procedural Programming may be the first programming paradigm that a new developer will learn. Fundamentally, the procedural code is the one that directly instructs a device on how to finish a task in logical steps. This paradigm uses a linear top-down approach and treats data and procedures as two different entities. Based on the concept of a procedure call, Procedural Programming divides the program into procedures, which are also known as routines or functions, simply containing a series of steps to be carried out. Simply put, Procedural Programming involves writing down a list of instructions to tell the computer what it should do step-by-step to finish the task at hand. Key Features of Procedural Programming The key features of procedural programming are given below:

  • Predefined functions: A predefined function is typically an instruction identified by a name. Usually, the predefined functions are built into higher-level programming languages, but they are derived from the library or the registry, rather than the program. One example of a pre-defined function is ‘charAt()’, which searches for a character position in a string.
  • Local Variable: A local variable is a variable that is declared in the main structure of a method and is limited to the local scope it is given. The local variable can only be used in the method it is defined in, and if it were to be used outside the defined method, the code will cease to work.
  • Global Variable: A global variable is a variable which is declared outside every other function defined in the code. Due to this, global variables can be used in all functions, unlike a local variable.
  • Modularity: Modularity is when two dissimilar systems have two different tasks at hand but are grouped together to conclude a larger task first. Every group of systems then would have its own tasks finished one after the other until all tasks are complete.
  • Parameter Passing: Parameter Passing is a mechanism used to pass parameters to functions, subroutines or procedures. Parameter Passing can be done through ‘pass by value’, ‘pass by reference’, ‘pass by result’, ‘pass by value-result’ and ‘pass by the name’.

Advantages and Disadvantages of Procedural Programming Procedural Programming comes with its own set of pros and cons, some of which are mentioned below. Advantages

  • Procedural Programming is excellent for general-purpose programming
  • The coded simplicity along with ease of implementation of compilers and interpreters
  • A large variety of books and online course material available on tested algorithms, making it easier to learn along the way
  • The source code is portable, therefore, it can be used to target a different CPU as well
  • The code can be reused in different parts of the program, without the need to copy it
  • Through Procedural Programming technique, the memory requirement also slashes
  • The program flow can be tracked easily Disadvantages
  • The program code is harder to write when Procedural Programming is employed
  • The Procedural code is often not reusable, which may pose the need to recreate the code if is needed to use in another application
  • Difficult to relate with real-world objects
  • The importance is given to the operation rather than the data, which might pose issues in some data-sensitive cases
  • The data is exposed to the whole program, making it not so much security friendly There are different types of programming paradigm as we mentioned before, which are nothing but a style of programming. It is important to understand that the paradigm does not cater to a specific language but to the way the program is written. Below is a comparison between Procedural Programming and Object-Oriented Programming.

Modular Oriented

Modular programming is the process of subdividing a computer program into separate sub-programs. A module is a separate software component. It can often be used in a variety of applications and functions with other components of the system.

  • Some programs might have thousands or millions of lines and to manage such programs it becomes quite difficult as there might be too many of syntax errors or logical errors present in the program, so to manage such type of programs concept of modular programming approached.
  • Each sub-module contains something necessary to execute only one aspect of the desired functionality.
  • Modular programming emphasis on breaking of large programs into small problems to increase the maintainability, readability of the code and to make the program handy to make any changes in future or to correct the errors. Points which should be taken care of prior to modular program development:
  • Limitations of each and every module should be decided.
  • In which way a program is to be partitioned into different modules.
  • Communication among different modules of the code for proper execution of the entire program. Advantages of Using Modular Programming Approach
  • Ease of Use : This approach allows simplicity, as rather than focusing on the entire thousands and millions of lines code in one go we can access it in the form of modules. This allows ease in debugging the code and prone to less error.
  • Reusability : It allows the user to reuse the functionality with a different interface without typing the whole program again.
  • Ease of Maintenance : It helps in less collision at the time of working on modules, helping a team to work with proper collaboration while working on a large application.

What Is Object-Oriented Programming (OOP)

OOP is an approach to programming which recognizes life as we know it as a collection of objects, which work in tandem with each other to solve a particular problem at hand. The primary thing to know about OOP is encapsulation, which is the idea that each object which holds the program is self-sustainable, which means that all the components that make up the object are within the object itself. Now since each module within this paradigm is self-sustainable, objects can be taken from one program and used to resolve another problem at hand with little or no alterations. Advantages

  • Due to modularity and encapsulation, OOP offers ease of management
  • OOP mimics the real world, making it easier to understand
  • Since objects are whole within themselves, they are reusable in other programs Disadvantages
  • Object-Oriented programs tend to be slower and use up a high amount of memory
  • Over-generalization
  • Programs built using this paradigm may take longer to be created

Procedural Programming vs Object-Oriented Programming: Head to Head Comparison

Procedural Programming

  • Uses immutable data
  • Follows the declarative programming model
  • Extends support to parallel programming
  • The execution order of statements is not the primary focus
  • Flow control is performed using function calls
  • Uses recursion concept to iterate collective data
  • No such side-effects of its functions
  • The focus in Procedural Programming is on ‘What You are Doing’
  • It Deals with algorithm
  • Program are divided in function
  • Needs Less Memory
  • Top Down Approach
  • Does not Access specifier
  • Overloading not possible
  • Less Secure
  • Data Hiding Not possible

Object-Oriented Programming

  • Uses mutable data
  • Follows the imperative programming model
  • Not suitable for parallel programming
  • The execution order of statements is very important
  • Flow control is performed through conditional statements and loops
  • Uses loop concept to iterate collection data
  • The method can have certain side-effects
  • The focus in Object-Oriented Programming is on ‘How You are Doing It’
  • It deals with object
  • Program are divided into object
  • Needs more then POP memory
  • Bottom up Approach
  • It have Access specifier
  • Overloading is Possible
  • Highly Secure
  • Data Hiding is Possible

Another highly used programming paradigm is Functional Programming. Functional Programming is way differs from both Procedural Programming and Object-Oriented Programming as it makes use of mathematical functions. Through this, the operations are performed only on the basis of the inputs that are entered, and they do not rely on temporary or hidden variables. Advantages

  • Functional Programming offers a protected environment
  • While many other languages require a substantial amount of information in order to perform operations properly, function programming eliminates the need for a large amount of code needed to define states
  • Since this paradigm is only dependent on the input arguments, there are no side-effects Disadvantages
  • Using Functional programming solely in commercial software development is not recommended and done
  • It requires a large amount of memory and time
  • It can prove to be less efficient than other paradigms

Generic Programming Techniques

Generic programming is about generalizing software components so that they can be easily reused in a wide variety of situations. In C++, class and function templates are particularly effective mechanisms for generic programming because they make the generalization possible without sacrificing efficiency. The key idea of generic programming or programming with templates is to define families of functions or classes. By providing the concrete type you get automatically a function or a class for this type. Generic programming provides similar abstraction like object-oriented programming. A big difference is that polymorphism of object-oriented programming will happen at runtime; that polymorphism of generic programming will happen in C++ at compile time. That the reason why polymorphism at runtime is often called dynamic polymorphism but polymorphism at compile is often called static polymorphism. By using the function template I can exchange arbitrary objects.

template <typename T> void xchg(T& x, T& y){   
  T t= x;
  x= y;
  y= t;
};
int i= 10;
int j= 20;
Man huber;
Man maier;

xchg(i,j);
xchg(huber,maier);

It doesn't matter for the function template, if I exchange numbers or men (line 11 and 12). In addition, I have not to specify the type parameter (line) because the compiler can derived it from the function arguments (line 11 and 12). The automatic type deduction of function templates will not hold for class templates. In the concrete case I have to specify the type parameter T and the non-type parameter N (line 1).

template <typename T, int N>
class Array{
public:
  int getSize() const{
    return N;
  }
private:
  T elem[N];
};

Array<double,10> doubleArray;
std::cout << doubleArray.getSize() << std::endl;

Array<Man,5> manArray;
std::cout << manArray.getSize() << std::endl;

Accordingly, the application of the class template Array is independent of the fact, whether I use doubles or men.

Need of Object-Oriented Programming

1. Modularity for easier troubleshooting

Something has gone wrong, and you have no idea where to look. Is the problem in the Widget file, or is it the WhaleFlumper? Will you have to trudge through that “sewage.c” file? Hope you commented your code! When working with object-oriented programming languages, you know exactly where to look. “Oh, the car object broke down? The problem must be in the Car class!” You don’t have to muck through anything else. That’s the beauty of encapsulation. Objects are self-contained, and each bit of functionality does its own thing while leaving the other bits alone. Also, this modality allows an IT team to work on multiple objects simultaneously while minimizing the chance that one person might duplicate someone else’s functionality. We can help you find your next programming job:

2. Reuse of code through inheritance

Suppose that in addition to your Car object, one colleague needs a RaceCar object, and another needs a Limousine object. Everyone builds their objects separately but discover commonalities between them. In fact, each object is really just a different kind of Car. This is where the inheritance technique saves time: Create one generic class (Car), and then define the subclasses (RaceCar and Limousine) that are to inherit the generic class’s traits. Of course, Limousine and RaceCar still have their unique attributes and functions. If the RaceCar object needs a method to “fireAfterBurners” and the Limousine object requires a Chauffeur, each class could implement separate functions just for itself. However, because both classes inherit key aspects from the Car class, for example the “drive” or “fillUpGas” methods, your inheriting classes can simply reuse existing code instead of writing these functions all over again. What if you want to make a change to all Car objects, regardless of type? This is another advantage of the OO approach. Simply make a change to your Car class, and all car objects will simply inherit the new code.

3. Flexibility through polymorphism

Riffing on this example, you now need just a few drivers, or functions, like “driveCar,” driveRaceCar” and “DriveLimousine.” RaceCarDrivers share some traits with LimousineDrivers, but other things, like RaceHelmets and BeverageSponsorships, are unique. This is where object-oriented programming’s sweet polymorphism comes into play. Because a single function can shape-shift to adapt to whichever class it’s in, you could create one function in the parent Car class called “drive” — not “driveCar” or “driveRaceCar,” but just “drive.” This one function would work with the RaceCarDriver, LimousineDriver, etc. In fact, you could even have “raceCar.drive(myRaceCarDriver)” or “limo.drive(myChauffeur).”

4. Effective problem solving

A language like C has an amazing legacy in programming history, but writing software in a top-down language is like playing Jenga while wearing mittens. The more complex it gets, the greater the chance it will collapse. Meanwhile, writing a functional-style program in a language like Haskell or ML can be a chore. Object-oriented programming is often the most natural and pragmatic approach, once you get the hang of it. OOP languages allows you to break down your software into bite-sized problems that you then can solve — one object at a time. This isn’t to say that OOP is the One True Way. However, the advantages of object-oriented programming are many. When you need to solve complex programming challenges and want to add code tools to your skill set, OOP is your friend — and has much greater longevity and utility than Pac-Man or parachute pants.

Also,

  • Possible to map objects in the problem domain
  • Data Hiding : Security
  • Inheritance : Eliminate redundancy , reusability
  • Its flexibility
  • It makes the coding more organized
  • Simple maintenance, an advanced analysis of complicated programs

Fundamentals of Object Oriented Programming

Java - What are Classes and Objects?

Object

image.png Any entity that has state and behavior is known as an object. For example, a chair, pen, table, keyboard, bike, etc. It can be physical or logical. An Object can be defined as an instance of a class. An object contains an address and takes up some space in memory. Objects can communicate without knowing the details of each other's data or code. The only necessary thing is the type of message accepted and the type of response returned by the objects. Example: A dog is an object because it has states like color, name, breed, etc. as well as behaviors like wagging the tail, barking, eating, etc.

Class

Collection of objects is called class. It is a logical entity. A class can also be defined as a blueprint from which you can create an individual object. Class doesn't consume any space. Classes and objects are the two main aspects of object-oriented programming.Look at the following illustration to see the difference between class and objects: class

  • Fruit

objects

  • Apple
  • Banana
  • Mango

Another example:

class

  • Car

objects

  • Volvo
  • Audi
  • Toyota

So, a class is a template for objects, and an object is an instance of a class. When the individual objects are created, they inherit all the variables and methods from the class.

Data Member and Methods

An object may contain values which are stored internally and are unique to that object. In order to do this, each value needs an appropriate declaration as a data member in the class. A data member may be of any type, including classes already defined, pointers to objects of any type, or even references to objects of any type. Data members may be private or public, but are usually held private so that values may only be changed at the discretion of the class function members. In the example below, the class C contains two a private data member of type int, and a public data member of type pointer to char. Types of Data Members: - We know that a class is a collection of data members and methods. In java programming we have two types of data members they are

                 1. Instance/non-static data members
                 2. Static data members

Types of Methods: - We know that each and every method is meant for performing some operation. In java programming we have two types of methods they are

              1. Instance/ non –static methods
             2.  Static methods

Instance methods: -

   1. Instance methods are always recommended to perform repeated operations like 
        reading records from the file, reading records from the data base etc…

   2. Programmatically instance methods definitions should not be preceded by a 
        keyword static.

  Syntax: -
          Return type method name (list of parameters if any)
          {
             Block of statements;
          }
    3. Each and every instance method must be access with respective Object name.

    4. Result of instance method is not sharable

  Ex: -
          void getTotal()
          {
             Tot= m1+ m2+ m3;
          }

Static methods: -

   1. Static methods are always which are recommended to perform one operation like 
       opening the files, obtaining a data base connection etc…

   2. Programmatically static methods definitions must be preceded by static keyword.

 Syntax: -
                Static Return type method name (list of parameters if any)
                {
                                Block of statements;
                }
   3. Each and every static method must be accessed with respect class name.

   4. Result set of static method always sharable

  Ex: -
                Public static void main ()
                {
                                S1.getTotal();
                                S2.getTotal();
                }

Note: - A class of java contains instance data members, static data members and instance methods static methods. Instance data members and instance methods will be access with respective to . Static data members and static methods will be access with respective to .

                      System.out.println (-)   ===== > 1
                      System.out.print (-)   ===== >    2
        Statement 1 is used for displaying the result of java program on the console (monitor) line by line.

        Statement 2 is used for displaying the result of java program on the console (monitor) in the same line.

Java Classes/Objects

Java is an object-oriented programming language. Everything in Java is associated with classes and objects, along with its attributes and methods. For example: in real life, a car is an object. The car has attributes, such as weight and color, and methods, such as drive and brake. A Class is like an object constructor, or a "blueprint" for creating objects.

Create a Class To create a class, use the keyword class: Main.java Create a class named "Main" with a variable x:

public class Main {
  int x = 5;
}

Remember from the Java Syntax chapter that a class should always start with an uppercase first letter, and that the name of the java file should match the class name.

Create an Object

In Java, an object is created from a class. We have already created the class named MyClass, so now we can use this to create objects. To create an object of MyClass, specify the class name, followed by the object name, and use the keyword new: Example Create an object called "myObj" and print the value of x:

public class Main {
  int x = 5;
  public static void main(String[] args) {
    Main myObj = new Main();
    System.out.println(myObj.x);
  }
}

Multiple Objects You can create multiple objects of one class: Example Create two objects of Main:

public class Main {
  int x = 5;

  public static void main(String[] args) {
    Main myObj1 = new Main();  // Object 1
    Main myObj2 = new Main();  // Object 2
    System.out.println(myObj1.x);
    System.out.println(myObj2.x);
  }
}

Using Multiple Classes

You can also create an object of a class and access it in another class. This is often used for better organization of classes (one class has all the attributes and methods, while the other class holds the main() method (code to be executed)). Remember that the name of the java file should match the class name. In this example, we have created two files in the same directory/folder: • Main.java • Second.java Main.java

public class Main {
  int x = 5;
}
Second.java
class Second {
  public static void main(String[] args) {
    Main myObj = new Main();
    System.out.println(myObj.x);
  }
}

When both files have been compiled:

C:\Users\Your Name>javac Main.java
C:\Users\Your Name>javac Second.java

Run the Second.java file:

C:\Users\Your Name>java Second

And the output will be:

5

Encapsulation

The meaning of Encapsulation, is to make sure that "sensitive" data is hidden from users. To achieve this, you must: • declare class variables/attributes as private • provide public get and set methods to access and update the value of a private variable


Get and Set You learned from the previous chapter that private variables can only be accessed within the same class (an outside class has no access to it). However, it is possible to access them if we provide public get and set methods. The get method returns the variable value, and the set method sets the value. Syntax for both is that they start with either get or set, followed by the name of the variable, with the first letter in upper case: Example

public class Person {
  private String name; // private = restricted access

  // Getter
  public String getName() {
    return name;
  }

  // Setter
  public void setName(String newName) {
    this.name = newName;
  }
}

Example explained The get method returns the value of the variable name. The set method takes a parameter (newName) and assigns it to the name variable. The this keyword is used to refer to the current object. However, as the name variable is declared as private, we cannot access it from outside this class: Example

public class Main {
  public static void main(String[] args) {
    Person myObj = new Person();
    myObj.name = "John";  // error
    System.out.println(myObj.name); // error 
  }
}

If the variable was declared as public, we would expect the following output: John However, as we try to access a private variable, we get an error:

MyClass.java:4: error: name has private access in Person
    myObj.name = "John";
         ^
MyClass.java:5: error: name has private access in Person
    System.out.println(myObj.name);
                  ^
2 errors

Instead, we use the getName() and setName() methods to acccess and update the variable: Example

public class Main {
  public static void main(String[] args) {
    Person myObj = new Person();
    myObj.setName("John"); // Set the value of the name variable to "John"
    System.out.println(myObj.getName());
  }
}

// Outputs "John"

Why Encapsulation?

  • Better control of class attributes and methods
  • Class attributes can be made read-only (if you only use the get method), or write-only (if you only use the set method)
  • Flexible: the programmer can change one part of the code without affecting other parts
  • Increased security of data

Inheritance

Inheritance: Inheritance is an important pillar of OOP(Object Oriented Programming). It is the mechanism in java by which one class is allow to inherit the features(fields and methods) of another class. Important terminology:

  • Super Class: The class whose features are inherited is known as superclass(or a base class or a parent class).
  • Sub Class: The class that inherits the other class is known as subclass(or a derived class, extended class, or child class). The subclass can add its own fields and methods in addition to the superclass fields and methods.
  • Reusability: Inheritance supports the concept of “reusability”, i.e. when we want to create a new class and there is already a class that includes some of the code that we want, we can derive our new class from the existing class. By doing this, we are reusing the fields and methods of the existing class.

Types of Inheritance

Single Inheritance: In single inheritance, a class is allowed to inherit from only one class. i.e. one sub class is inherited by one base class only.

image.png

Multiple Inheritance: Multiple Inheritance is a feature of C++ where a class can inherit from more than one classes. i.e one sub class is inherited from more than one base classes.

image.png

Multilevel Inheritance: In this type of inheritance, a derived class is created from another derived class.

image.png Hierarchical Inheritance: In this type of inheritance, more than one sub class is inherited from a single base class. i.e. more than one derived class is created from a single base class.

image.png

Hybrid (Virtual) Inheritance: Hybrid Inheritance is implemented by combining more than one type of inheritance. For example: Combining Hierarchical inheritance and Multiple Inheritance. Below image shows the combination of hierarchical and multiple inheritance:

image.png A special case of hybrid inheritance : Multipath inheritance: A derived class with two base classes and these two base classes have one common base class is called multipath inheritance. An ambiguity can arrise in this type of inheritance.

image.png In the above example, both ClassB & ClassC inherit ClassA, they both have single copy of ClassA. However ClassD inherit both ClassB & ClassC, therefore ClassD have two copies of ClassA, one from ClassB and another from ClassC. If we need to access the data member a of ClassA through the object of ClassD, we must specify the path from which a will be accessed, whether it is from ClassB or ClassC, bco’z compiler can’t differentiate between two copies of ClassA in ClassD.

There are 2 ways to avoid this ambiguity:

  1. Use scope resolution operator
  2. Use virtual base class Avoiding ambiguity using scope resolution operator: Using scope resolution operator we can manually specify the path from which data member a will be accessed.. To inherit from a class, use the extends keyword. In the example below, the Car class (subclass) inherits the attributes and methods from the Vehicle class (superclass): Example ``` class Vehicle { protected String brand = "Ford"; // Vehicle attribute public void honk() { // Vehicle method System.out.println("Tuut, tuut!"); } }

class Car extends Vehicle { private String modelName = "Mustang"; // Car attribute public static void main(String[] args) {

// Create a myCar object
Car myCar = new Car();

// Call the honk() method (from the Vehicle class) on the myCar object
myCar.honk();

// Display the value of the brand attribute (from the Vehicle class) and the value of the modelName from the Car class
System.out.println(myCar.brand + " " + myCar.modelName);

} } ``` Did you notice the protected modifier in Vehicle?We set the brand attribute in Vehicle to a protected access modifier. If it was set to private, the Car class would not be able to access it Why And When To Use "Inheritance"?

  • It is useful for code reusability: reuse attributes and methods of an existing class when you create a new class.

Polymorphism

Polymorphism means "many forms", and it occurs when we have many classes that are related to each other by inheritance. Like we specified in the previous chapter; Inheritance lets us inherit attributes and methods from another class. Polymorphism uses those methods to perform different tasks. This allows us to perform a single action in different ways. For example, think of a superclass called Animal that has a method called animalSound(). Subclasses of Animals could be Pigs, Cats, Dogs, Birds - And they also have their own implementation of an animal sound (the pig oinks, and the cat meows, etc.): Example

class Animal {
  public void animalSound() {
    System.out.println("The animal makes a sound");
  }
}

class Pig extends Animal {
  public void animalSound() {
    System.out.println("The pig says: wee wee");
  }
}

class Dog extends Animal {
  public void animalSound() {
    System.out.println("The dog says: bow wow");
  }
}

Remember from the Inheritance that we use the extends keyword to inherit from a class. Now we can create Pig and Dog objects and call the animalSound() method on both of them: Example

class Animal {
  public void animalSound() {
    System.out.println("The animal makes a sound");
  }
}

class Pig extends Animal {
  public void animalSound() {
    System.out.println("The pig says: wee wee");
  }
}

class Dog extends Animal {
  public void animalSound() {
    System.out.println("The dog says: bow wow");
  }
}

class Main {
  public static void main(String[] args) {
    Animal myAnimal = new Animal();  // Create a Animal object
    Animal myPig = new Pig();  // Create a Pig object
    Animal myDog = new Dog();  // Create a Dog object
    myAnimal.animalSound();
    myPig.animalSound();
    myDog.animalSound();
  }
}

Why And When To Use "Inheritance" and "Polymorphism"?

  • It is useful for code reusability: reuse attributes and methods of an existing class when you create a new class.

Abstract Classes and Methods

Data abstraction is the process of hiding certain details and showing only essential information to the user. Abstraction can be achieved with either abstract classes or interfaces (which you will learn more about in the next chapter). The abstract keyword is a non-access modifier, used for classes and methods:

  • Abstract class: is a restricted class that cannot be used to create objects (to access it, it must be inherited from another class).
  • Abstract method: can only be used in an abstract class, and it does not have a body. The body is provided by the subclass (inherited from). An abstract class can have both abstract and regular methods:
    abstract class Animal {
    public abstract void animalSound();
    public void sleep() {
      System.out.println("Zzz");
    }
    }
    
    From the example above, it is not possible to create an object of the Animal class: Animal myObj = new Animal(); // will generate an error To access the abstract class, it must be inherited from another class. Example
// Abstract class
abstract class Animal {
  // Abstract method (does not have a body)
  public abstract void animalSound();
  // Regular method
  public void sleep() {
    System.out.println("Zzz");
  }
}

// Subclass (inherit from Animal)
class Pig extends Animal {
  public void animalSound() {
    // The body of animalSound() is provided here
    System.out.println("The pig says: wee wee");
  }
}

class Main {
  public static void main(String[] args) {
    Pig myPig = new Pig(); // Create a Pig object
    myPig.animalSound();
    myPig.sleep();
  }
}

Why And When To Use Abstract Classes and Methods? To achieve security - hide certain details and only show the important details of an object.

Static vs Dynamic Binding in Java

Static Binding: The binding which can be resolved at compile time by compiler is known as static or early binding. Binding of all the static, private and final methods is done at compile-time . Why binding of static, final and private methods is always a static binding? Static binding is better performance wise (no extra overhead is required). Compiler knows that all such methods cannot be overridden and will always be accessed by object of local class. Hence compiler doesn’t have any difficulty to determine object of class (local class for sure). That’s the reason binding for such methods is static. Let’s see by an example

public class NewClass { 
    public static class superclass { 
        static void print() 
        { 
            System.out.println("print in superclass."); 
        } 
    } 
    public static class subclass extends superclass { 
        static void print() 
        { 
            System.out.println("print in subclass."); 
        } 
    } 

    public static void main(String[] args) 
    { 
        superclass A = new superclass(); 
        superclass B = new subclass(); 
        A.print(); 
        B.print(); 
    } 
}

Before scrolling further down, Guess the output of the above program?

Output:
print in superclass.
print in superclass.

As you can see, in both cases print method of superclass is called. Lets see how this happens

  • We have created one object of subclass and one object of superclass with the reference of the superclass.
  • Since the print method of superclass is static, compiler knows that it will not be overridden in subclasses and hence compiler knows during compile time which print method to call and hence no ambiguity.

Dynamic Binding: In Dynamic binding compiler doesn’t decide the method to be called. Overriding is a perfect example of dynamic binding. In overriding both parent and child classes have same method . Let’s see by an example

public class NewClass { 
    public static class superclass { 
        void print() 
        { 
            System.out.println("print in superclass."); 
        } 
    } 

    public static class subclass extends superclass { 
        @Override
        void print() 
        { 
            System.out.println("print in subclass."); 
        } 
    } 

    public static void main(String[] args) 
    { 
        superclass A = new superclass(); 
        superclass B = new subclass(); 
        A.print(); 
        B.print(); 
    } 
}

Output:

print in superclass.
print in subclass.

Here the output differs. But why? Let’s break down the code and understand it thoroughly.

  • Methods are not static in this code.
  • During compilation, the compiler has no idea as to which print has to be called since compiler goes only by referencing variable not by type of object and therefore the binding would be delayed to runtime and therefore the corresponding version of print will be called based on type on object.

Important Points

  • private, final and static members (methods and variables) use static binding while for virtual methods (In Java methods are virtual by default) binding is done during run time based upon run time object.
  • Static binding uses Type information for binding while Dynamic binding uses Objects to resolve binding.
  • Overloaded methods are resolved (deciding which method to be called when there are multiple methods with same name) using static binding while overridden methods using dynamic binding, i.e, at run time.

Message Passing in Java

  • What is message passing and why it is used? Message Passing in terms of computers is communication between processes. It is a form of communication used in object-oriented programming as well as parallel programming. Message passing in Java is like sending an object i.e. message from one thread to another thread. It is used when threads do not have shared memory and are unable to share monitors or semaphores or any other shared variables to communicate. Suppose we consider an example of producer and consumer, likewise what producer will produce, the consumer will be able to consume that only. We mostly use Queue to implement communication between threads.

image.png

Case Study Assignment

interface FunctionOfVehicles{
    public abstract void GearChange(int a);
    public abstract void SpeedUp(int a);
    public abstract void Break(int a);
}

class Car implements FunctionOfVehicles{
    int gear = 1, Speed = 0;
    public void GearChange(int a) {
        if(a==1) {
            gear = gear +1;
        }
        else if (a==0) {
            gear = gear -1;
        }
        else {
            System.out.println("Invalid Input");
        }
        System.out.println("Current Gear is "+ this.gear);
    }
    public void SpeedUp(int a) {
        if(a==1) {
            Speed = Speed + 20;
        }
        else if (a==0) {
            Speed = Speed  - 20;
        }
        else {
            Speed = Speed  + a;
        }
        System.out.println("Current Speed is "+ this.Speed);
    }
    public void Break(int a) {
        if (a==1) {
            System.out.println("Stopped");
        }
        else {
            System.out.println("Motion");
        }
    }

}

class Bike implements FunctionOfVehicles{
    int gear = 1, Speed = 0;
    public void GearChange(int a) {
        if(a==1) {
            gear = gear +1;
        }
        else if (a==0) {
            gear = gear -1;
        }
        else {
            System.out.println("Invalid Input");
        }
        System.out.println("Current Gear is "+ this.gear);
    }
    public void SpeedUp(int a) {
        if(a==1) {
            Speed = Speed + 10;
        }
        else if (a==0) {
            Speed = Speed  - 10;
        }
        else {
            Speed = Speed  + a;
        }
        System.out.println("Current Speed is "+ this.Speed);
    }
    public void Break(int a) {
        if (a==1) {
            System.out.println("Stopped");
        }
        else {
            System.out.println(" Motion");
        }
    }

}


public class Vehicles {

    public static void main(String args[]) {

        Car c = new Car();
        Bike b = new Bike();

        c.GearChange(1);
        c.SpeedUp(1);
        c.GearChange(1);
        c.SpeedUp(40);
        c.GearChange(0);
        c.SpeedUp(-30);
        c.Break(1);
        c.GearChange(1);
        c.SpeedUp(1);
        c.GearChange(1);
        c.SpeedUp(40);
        c.GearChange(0);
        c.SpeedUp(-30);
        c.Break(1);

        b.GearChange(1);
        b.SpeedUp(1);
        b.GearChange(1);
        b.SpeedUp(40);
        b.GearChange(0);
        b.SpeedUp(-30);
        b.Break(1);

    }
}

OUTPUT

Current Gear is 2
Current Speed is 20
Current Gear is 3
Current Speed is 60
Current Gear is 2
Current Speed is 30
Stopped
Current Gear is 3
Current Speed is 50
Current Gear is 4
Current Speed is 90
Current Gear is 3
Current Speed is 60
Stopped
Current Gear is 2
Current Speed is 10
Current Gear is 3
Current Speed is 50
Current Gear is 2
Current Speed is 20
Stopped