Oops
Oops
( OOPS )
If you want to develop a software application, you have to use one of
the two programming paradigms(models).
1. Procedure Oriented Programming model
2. Object Oriented Programming model.
In POP model, the applications are developed by creating multiple
functions.
For a small scale application, POP model is suitable.
But for large scale applications, if many functions are created in the
program, then it is difficult to find out which function is modifying
which data. So increases complexity.
So, another programming model called OOP was introduced to develop
any scale applications.
In POP, the data exists at one place and the logic on the data exists at
another place. So it kills the readability.
In OOP, the data and the logic on that data will exist at one place. So it
improves the readability.
C and Pascal are the Procedure Oriented Programming languages.
Java, Python , … are the Object Oriented Programming languages.
The principles of Object Oriented Programming System
are,
1. abstraction
2. encapsulation
3. inheritance
4. polymorphism
If a programming language provides a way to implement
these principles in an application then it is called Object
Oriented programming language.
abstraction:
It is a process of showing essential information and
hiding un-essential information based on the user of
a system.
For example, in a banking system, the users are
clerks, accountants and managers.
The information shown to the clerks is less than the
information shown to the accountants and it is less
than the information shown to the managers. This is
abstraction.
Suppose, you are calling a method of Java API, you
are given with method name, parameters and return
type information, but not the logic of the method.
This is called abstraction.
Java allows the programmers/developers to
implement abstraction in two ways.
1. using abstract classes
2. using interfaces.
encapsulation:
It is a process of combining the data and related
functionality together at a single place/unit, to
protect the data from un-authorized modification.
we can implement encapsulation in Java, by creating
a class with private variables and public getter and
setter methods.
inheritance:
It is a process of creating new classes from existing
classes to achieve re-usability and to avoid
redundancy. (duplication of code).
The newly created class is called child class and the
existing class is parent class.
The newly created class inherits properties and the
behavior from the existing class.
In Java, extends keyword is given to implement
inheritance.
polymorphism:
polymorphism word is constructed from two greek
words poly and morphos.
poly denotes many and morphos denotes forms.
polymorphism denotes many forms.
A functionality can have many forms.
To implement/define a functionality, we create
methods.
For ex, address verification in a banking system is a
functionality and it has multiple forms like with
adhaar card, or with voter id, etc..
In Java, we can implement polymorphism using two
mechanisms.
1. method overloading
2. method overriding
class Employee {
int empno;
String ename;
double salary;
void display() {
System.out.println("empno : " + empno);
System.out.println("ename : " + ename);
System.out.println("salary : " + salary);
}
}
System.out.println("==================================
=");
}
/*
* write a program to create a class Player
* with attributes playerId, playerName and
* playerRank.
* Define a method to display the player details.
* In main method, create two objects for Player class,
* initialize the objects with data and display
*/
package com.ait.oop;
class Player {
int playerId;
String playerName;
int playerRank;
void display() {
System.out.println("Player id : " + playerId);
System.out.println("player name : " + playerName);
System.out.println("player rank : " + playerRank);
}
}
public class TestClass {
System.out.println("===================");
Player player2 = new Player();
player2.playerId = 10202;
player2.playerName = "NEERAJ";
player2.playerRank = 2;
player2.display();
/*
* write a program to create a class Employee
* with attributes empno, ename and salary.
* Define setter and getter methods for the properties.
* In main method, create an object, call the setter
* methods to store the values, then display
*/
package com.ait.oop;
class Employee {
private int empno;
private String ename;
private double salary;
void display() {
System.out.println("empno : " + empno);
System.out.println("ename : " + ename);
System.out.println("salary : " + salary);
}
}
e1.display();
System.out.println("==================================
=");
constructor
------------
Initializing an object means, assigning some values to
the data members.
Constructor is a special method in a class, which is used
to initialize the data members, while creating an object.
Suppose, if we don’t create a constructor in a class, then
JVM will provide a default constructor and it will initialize
the data members with default values, based on the data
type of the data members.
If you want to initialize the data members with
meaningful data, then you have to define a constructor
in your class.
Constructor is a special method, because of the below
reasons.
1. constructor does not contain return type.
2. constructor name must be same as the class name.
3. constructor is automatically executed while creating
an object.
for ex:
class ClassA {
int x; This class has no constructor,
int y; so JVM will provide default
} constructor.
For ex:
class ClassOne {
int x; This class has a constructor.
int y; So, JVM will not provide any
ClassOne() { default constructor.
x = 10;
y = 20;
}
}
Types of constructors:
1. parameter-less constructor (or) constructor without
arguments.
2. parameterized constructor (or) constructor with
arguments.
When we want to initialize the multiple objects with same
data for the data members then we define parameter-less
constructor.
When we want to initialize the objects with different data for
the data members then we define parameterized constructor.
For ex:
class ClassA {
int x;
int y;
ClassA() { //parameter-less constructor
x = 100;
y = 200;
}
ClassA(int x, int y) { //parameterized constructor
this.x = x;
this.y = y;
}
}
|| DATE: 19-Aug-24 ||
this keyword:
-------------
ex1:
In the above example, the parameters names are a,b and
attributes names are x and y in the constructor.
The parameters names and attributes names are different.
So, using this keyword is optional.
ex2:
//compile-time error
Employee.display();
//correct
double y = Employee.calculateBonus(4000.0);
}
}
static block:
------------
The purpose of creating a static block is to initialize the static
variables of a class.
If we initialize the static variable in a constructor, then for
every object creation of that class, constructor will be
executed and it will re-initialize the static variable again and
again.
That’s why we use static block.
static block will be executed for only once, when the class is
loaded into JVM.
In a class, we can define multiple static blocks also.
If mulitple static blocks are defined then they are executed in
the same order of the definitions.
ex:
class A {
private int x;
private static int y;
static { // static block
y = 50;
}
A(int x) { //constructor
this.x = x;
}
}
==========================================
=========
|| DATE: 26 – Aug – 24 ||
/*
* create a class called Booking with the below
* attributes/fields.
* bookingId
* bookingDate
* seatsRequired
* seatsAvailable
* Define methods to book/cancel the seats.
* In main method, create one or more objects for
* Booking class, invoke the methods.
*
*/
import java.time.LocalDate;
import java.util.Random;
class Booking {
private long bookingId;
private LocalDate bookingDate;
private int seatsRequired;
private static int seatsAvailable;
static {
seatsAvailable = 10;
}
}
public void cancelSeats() {
seatsAvailable = seatsAvailable + this.seatsRequired;
System.out.println("seats are cancelled!!");
System.out.println("The available seats after cancellation : " +
Booking.fetchAvailableSeats());
}
return seatsAvailable;
}
}
public class MainClass {
System.out.println("==================================
===================");
System.out.println("==================================
==================");
booking1.cancelSeats();
System.out.println("==================================
=================");
booking2.bookSeats();
output:
Booking successful! Your booking id : 16864654
The seats remaining after booking : 4
Booking Date : 2024-08-26
Seats booked : 6
==============================================
=======
Sorry, seats are not available!!
==============================================
======
seats are cancelled!!
The available seats after cancellation : 10
==============================================
=====
Booking successful! Your booking id : 15416963
The seats remaining after booking : 3
Booking Date : 2024-08-26
Seats booked : 7
Inner classes:
If we create a class inside another class then it is called inner
class.
When we have related classes, and a class can’t work
independently without the other class then
we can create that class in the other class.
For ex:
class Mobile {
}
class Sim {
}
The class Sim can’t work independently without Mobile class. So,
here we can create Sim class inside Mobile class.
class Mobile { // outer class
//variables
//methods
class Sim { // inner class
//variables
//methods
}
}
With inner classes, we can keep the related classes together
at one place for better encapsulation, readability and
maintianability.
private variables of outer class are visible to the inner class,
but private variables of inner class are not visible to the outer
class.
inner classes are 4 types.
1. non-static inner class
2. static inner class
3. local inner class
4. anonymous inner class
ex1:
class OuterClass {
class InnerClass { //non-static inner class
}
}
ex2:
class OuterClass {
static class InnerClass { //static inner class
}
}
ex3:
class OuterClass {
void m1() {
class InnerClass { //local inner class
}
}
}
Q) can we make inner class(static/non-static) as private?
A) yes.
Q) can we make local inner class as private?
A) No.
Q) can you make outer class as private?
A) No.
Q) can we make outer class as static?
A) No.
Q) If outer class and inner class has the same variable then which
variable gets more priority?
A) inner class variable gets priority.
ex:
class OuterClass {
private int x = 10;
class InnerClass {
private int x = 20;
}
}
public class Main {
}
output: 20
class InnerClass {
private int x = 20;
//outerclassname.innerclassname objectname =
outerclassobject.new innerclassname();
OuterClass.InnerClass innerClass = outerClass.new InnerClass();
innerClass.m11();
}
}
}
Inheritance
===========
while creating a new class, suppose if some of the properties
or methods are already exist in another class, then we create
the new class by inheriting the properites and behaviour from
the existing class. This is called inheritance.
Inheritance is a process of creating new classes from the
existing classes.
The class who is inheritance the properties/behaviour from
the existing class is called child class/sub class/derviced
class. That existing is called parent class/super class/base
class.
we use extends keyword to create a child class from the
parent class.
class ParentClass {
}
class ChildClass extends ParentClass {
}
Inheritance improves developer’s productivity, provides code
reusability, reduces redundency, reduces inconsistency and
improves readability.
Types of inheritance:
1. Single inheritance
2. Multi-level inheritance
3. Multiple inheritance
4. Hierarchical inheritance
5. Hybrid inheritance.
/*
* create a parent class Camera with attributes
* brand, resolution, price
* create a child class DigitalCamera with attributes
* storage, sensorType
* In main method, create child class object and display
* the details.
*/
/*
* The default parent class for any class in Java
* is java.lang.Object.
*/
class Camera { //parent class
private String brand;
private String resolution;
private double price;
//parameterized constructor
public Camera(String brand, String resolution, double price) {
super();
this.brand = brand;
this.resolution = resolution;
this.price = price;
}
//parameterized constructor
public DigitalCamera(String brand, String resolution, double price,
String storage, String sensorType) {
super(brand, resolution, price);
this.storage = storage;
this.sensorType = sensorType;
}
display();
System.out.println("Storage : " + storage);
System.out.println("Sensor Type : " + sensorType);
}
}
public class Main {
}
=====================================
============
super() call:
--------------
super() call calls parent class constructor.
super() call must be the first statement in the constructor.
if you don’t write the super() call then java compiler will
attach the super() call as a first statement by default.
ex1:
class A {
A() {
System.out.println("A : In parameter-less constructor");
}
}
class B extends A {
B() {
System.out.println("B : In parameter-less constructor");
}
}
public class Main {
ex2:
class A {
A(int x) {
System.out.println("A : In parameterized constructor(one
parameter)");
System.out.println("x = " + x);
}
}
class B extends A {
B() {
super(10);
System.out.println("B : In parameter-less constructor");
}
}
public class Main {
}
}
output:
A : In parameterized constructor(one parameter)
x = 10
B : In parameter-less constructor
ex3:
class A {
A(int x) {
System.out.println("A : In parameterized constructor(one
parameter)");
System.out.println("x = " + x);
}
}
class B extends A {
B(int x) {
super(x);
System.out.println("B : In parameter-less constructor");
}
}
public class Main {
}
}
output:
A : In parameterized constructor(one parameter)
x = 30
B : In parameter-less constructor
A : In parameterized constructor(one parameter)
x = 40
B : In parameter-less constructor
==============================================
==================
this() call :
-------------
this() call calls the same class constructor
this() call must be the first statement.
if we don’t write this() call, then super() call will be added by
the compiler.
we can’t write both super() call and this() call at a time.
Because, both calls must be the first statement in the
constructor and it is not possible.
ex:
class A {
A() {
System.out.println("A : In parameter-less constructor");
}
}
class B extends A {
B() {
this(100);
System.out.println("B : In parameter-less constructor");
}
B(int a) {
System.out.println("B : In parameterized constructor(one
parameter)");
}
}
public class Main {
output:
A : In parameter-less constructor
B : In parameterized constructor(one parameter)
B : In parameter-less constructor
|| DATE: 30-Aug-24 ||
In inheritance, we can store the child class object in the
parent class reference variable. But we can’t store the
parent class object in a child class reference variable.
ex:
class ClassA {
}
class ClassB extends ClassA {
}
class Main {
p s v m(String[] args) {
ClassA ca = new ClassB(); //valid
ClassB cb = new ClassA(); //error
}
}
class C extends A, B {
void m3() {
super.m1();
}
}
Here, child class is calling m1() method of the parent class.
But both the parent classes have m1() method. So, the
compiler gets ambiguity and it is an error.
/*
* write a program to implement the following.
* create Vehicle class with attributes speed and fuelType.
* Define parameterized constructor and a display() method.
* create Car class from Vehicle with attributes numberOfDoors and
* transmissionType. Define parameterized constructor and a display()
* method.
* create ElectricCar class from Car with attributes batteryCapacity
* and chargingTime. Define parameterized constructor and a dispaly()
* method.
* In main class, create ElectricCar object, and call the display()
* method.
*/
class Vehicle {
private int speed;
private String fuelType;
void display() {
System.out.println("speed : " + speed);
System.out.println("fuel type : " + fuelType);
}
}
class Car extends Vehicle {
}
class ElectricCar extends Car {
private int batteryCapacity;
private int chargingTime;
void display() {
super.display();
System.out.println("Battery capacity : " + batteryCapacity);
System.out.println("Charging time : " + chargingTime);
}
}
public class Main {
Polymorphism
Polymorphism means, multiple forms of doing a task.
Polymorphism is of two types:
1. static/compile-time polymorphism
2. dynamic/runtime polymorphism.
compile-time polymorphism can be implemented through
method overloading.
runtime polymorphism can be implemented through method
overriding.
method overloading:
method overloading means, defining the same method for
multiple times in the same class, but with a difference in
parameters.
for example, in String class, substring() method is
overloaded. Because, to return a portion of a string value,
there are two ways. one way is with begin index and other
way is with begin,end indexes.
substring(beginIndex)
substring(beginIndex, endIndex)
In method overloading, the methods must contain the same
name, but they must have the difference in parameters. The
difference could be,
1. number of parameters, or
2. data type of the parameters, or
3. order/sequence of the parameters.
ex:
class Recharge {
void doRecharge(long mobileNumber, double amount) {
System.out.println("doRecharge(mobileNumber, amount)");
}
void doRecharge(long mobileNumber, double amount, String
couponCode) {
System.out.println("doRecharge(mobileNumber, amount,
couponCode)");
}
}
public class Main {
}
In the above Recharge class, we have doRecharge() method
is defined for 2 times.
one time with 2 parameters and other time with 3
parameters. So, it is method overloading.
ex:
public class Login {
public boolean login(String username, String password)
{
}
public boolean login(String emailId, String password)
{
}
}
Here, login() method is defined for 2 times. But there is no
difference in number of parameters, or data type of the
parameters or in the order of the parameters. So it is not
method overloading. It generates a compile-time error.
ex:
class ClassA {
void m1(int x, double y) {
}
void m1(double a, int b) {
}
}
Here, m1() method is defined for 2 times. Both methods have
2 parameters, but their order is different. So, it is
overloading.
ex:
class Repository {
Employee find(int id) {
}
void find(int id) {
}
}
Here, find() method is defined 2 times. But there is no
difference in parameters. So, it is not method overloading.
It’s a compile-time error.
method overloading doesn’t depends on return type of a
method.
ex:
class A {
void m1(int x) {
}
}
class B extends A {
void m1(int x, int y) {
}
}
Here, child class has two m1() methods. One is inherited from
the parent class and the other one is defined in the child
class.
one m1() has one parameter and the other m1() method has
two parameters. So, it is method overloading.
@Override
static void sayHello() { //error
System.out.println("sayHello(): ClassB");
}
}
class ClassA {
void doCaliculationForTax() {
System.out.println("doCalicationForTax() : ClassA");
}
}
class ClassB extends ClassA {
@Override
public void doCaliculationForTax() {
System.out.println("doCaliculationForTax(): ClassB");
}
}
public class Main {
@Override
public double calculateInterest() {
return getBalance() * 0.15;
}
@Override
public double calculateInterest() {
return getBalance() * 0.25;
}
}
System.out.println("=======================");
HAS-A relationship:
Inheritance represents IS-A relationship between the class.
extends keyword can be read as IS-A
for ex:
class Mobile extends Product {
}
Mobile IS-A product
ex:
class ClassA {
ClassB classB; // HAS-A
ClassA() {
classB = new ClassB();
}
}
Here, ClassA is called as a dependent class and ClassB is
called as a dependency class.
HAS-A relationship can be either Aggregation or Composition.
Aggregation is a weak bonding/relation between a
depedent class and a dependency class.
For example.
class Policy {
Customer policyHolder;
Policy() {
policyHolder = new Customer();
}
}
Here, Policy is dependent class and Customer is dependency
class.
Customer class can work independently without Policy class
also. This is called weak bonding. So, the relationship is
called Aggregation.
Composition is a strong bonding/relation between dependent
and dependency classes.
ex:
class Person {
Passport passport;
Person() {
passport = new Passport();
}
}
Here, Person is a dependent class and Passport is a
dependency class.
Passport can’t work independently without a Person. So, it is
called composition.
final keyword:
final keyword can be used with the following.
1. variable
2. method
3. class
final indicates finalized/fixed.
If you declare a variable as final then it becomes like a
constant in a program.
If you declare a variable as final then it is object level
constant.
If you declare a variable as static final then it is class level
constant.
ex1:
class BankAccount {
private final long accountNumber;
private double balance;
}
here, accountNumber is declared as final, because its value is
fixed for an account object. It is object level constant.
ex2:
class MyMath {
public static final doule PI = 3.142;
}
here, PI is declared as a static final, because its value is fixed
for all instances of the MyMath class. It is class level
constant.
It is recommended to write the variable name in uppercase, if
a variable is static and final.
If a variable is final, we can define a getter method, but we
can’t define a setter method.
}
class MerchantFulfilledOrder extends Order {
}
ClassA(int x, int y) {
this.x = x;
this.y = y;
}
ClassB() {
super(10, 20);
}
@Override
void m1() {
System.out.println("overridden m1() in : ClassB");
System.out.println("x = " + x);
System.out.println("y = " + y);
}
}
Q) can we define a constructor in abstract class?
A) Yes.
Q) what is the use of the constructor in abstract class?
A) To initialize the data members of the abstract class.
Q) can we create object for abstract class?
A) No.
Q) can we create object for subclass of abstract class?
A) Yes. When we create child class object, its constuctor invokes the
abstract class constructor.
Q) I have 2 abstract methods in abstract class, but child class is
overriding only one abstract method. Will I get an error in the child
class?
A) Yes. To solve the error, either we have to override the both abstract
methods or else declare child class as abstract class.
InsurancePolicy(double basePremium) {
this.basePremium = basePremium;
}
@Override
public double calculateRiskFactor() {
double riskFactor = 0; //local variable
if(isSmoker) {
//add 15% extra for a smoker
riskFactor += basePremium * 0.15;
}
return riskFactor;
}
@Override
public double calculateRiskFactor() {
if ( mfgYear >= 2022 ) {
return basePremium * 0.10;
}
else {
return basePremium * 0.35;
}
}
}
Interfaces
//include DATE: 9-9-24 notes here
|| DATE: 10-9-24 ||
PaymentProcessor.java
public interface PaymentProcessor {
String processPayment(double amount);
boolean paymentStatus(String txId);
PaypalProcessor.java
import java.util.Random;
@Override
public String processPayment(double amount) {
if ( amount <= 0 ) {
return "ppnull101";
}
else {
return "pp"+new Random().nextInt(10000);
}
}
@Override
public boolean paymentStatus(String txId) {
if ( txId.startsWith("ppnull"))
return false;
else
return true;
}
StripeProcessor.java
import java.util.Random;
@Override
public String processPayment(double amount) {
@Override
public boolean paymentStatus(String txId) {
if ( txId.startsWith("spnull"))
return false;
else
return true;
}
Main.java
public class Main {
if ( paypal.paymentStatus(paypal.processPayment(amount)) ) {
System.out.println(amount + " : paid through paypal");
}
else {
System.out.println(amount + " : is invalid.");
}
amount = 9000;
if ( stripe.paymentStatus(stripe.processPayment(amount))) {
System.out.println(amount + " : paid through stripe");
}
else {
System.out.println(amount + " : is invalid");
}
}
}