0% found this document useful (0 votes)
3 views12 pages

Programming in Java_Inheritance

The document explains the concept of inheritance in Java, detailing how subclasses acquire fields and methods from superclasses, and the different types of inheritance such as single, multilevel, and hierarchical. It also covers method overriding, emphasizing runtime polymorphism and the rules for valid overrides, as well as the use of the super keyword to access parent class methods and fields. Additionally, it introduces abstract classes, which cannot be instantiated and require subclasses to implement abstract methods, allowing for shared code while enforcing specific behaviors in subclasses.

Uploaded by

dkt0887
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views12 pages

Programming in Java_Inheritance

The document explains the concept of inheritance in Java, detailing how subclasses acquire fields and methods from superclasses, and the different types of inheritance such as single, multilevel, and hierarchical. It also covers method overriding, emphasizing runtime polymorphism and the rules for valid overrides, as well as the use of the super keyword to access parent class methods and fields. Additionally, it introduces abstract classes, which cannot be instantiated and require subclasses to implement abstract methods, allowing for shared code while enforcing specific behaviors in subclasses.

Uploaded by

dkt0887
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

1.

Inheritance

Inheritance is the OOP mechanism by which one class (the subclass / child class) acquires the fields and
methods of another class (the superclass / parent class). It is declared in Java using the extends keyword.
Inheritance models an 'IS-A' relationship — a Dog IS-A Animal, a Car IS-A Vehicle.

class Parent {
// fields and methods
}

class Child extends Parent {


// Child automatically gets Parent's non-private members,
// and can add its own fields/methods, or override Parent's methods
}

Key rules to remember:


• Java supports only single inheritance for classes — a class can extend exactly one other class (no
'extends A, B'). Multiple inheritance of type is achieved only through interfaces.
• private members of the parent are NOT directly accessible in the child, though they still exist in
memory and can be reached through inherited public/protected methods.
• A subclass can add new fields/methods, and can override (redefine) an inherited method to change its
behaviour.
• Constructors are NOT inherited, but the parent's constructor always runs first when a child object is
created (implicitly via a hidden super(), or explicitly).
Types of inheritance in Java:

Type Description
Single One subclass, one superclass. class Dog extends Animal.

Multilevel A chain: class C extends B, class B extends A.

Hierarchical Multiple subclasses share one superclass: Dog and Cat both extend Animal.

Multiple (classes) NOT supported directly in Java — avoided to prevent the 'Diamond Problem'. Achieved
instead via interfaces.

Example 1: Basic Single Inheritance


class Animal {
void eat() {
[Link]("This animal eats food.");
}
}

class Dog extends Animal {


void bark() {
[Link]("The dog barks.");
}
}

public class Prog1 {


public static void main(String[] args) {
Dog d = new Dog();
[Link](); // inherited from Animal
[Link](); // Dog's own method
}
}
Output: This animal eats food.
The dog barks.

Dog did not define eat() itself, yet [Link]() works, because Dog extends Animal and automatically inherits its
public method.

Example 2: Method Overriding (Redefining Inherited Behaviour)


class Shape {
void draw() {
[Link]("Drawing a generic shape");
}
}

class Circle extends Shape {


@Override
void draw() {
[Link]("Drawing a circle");
}
}

public class Prog2 {


public static void main(String[] args) {
Shape s = new Circle(); // parent reference, child object
[Link]();
}
}

Output: Drawing a circle

Circle overrides draw() with its own version. Even though the reference type is Shape, Java calls the actual
object's (Circle's) method at runtime — this is runtime polymorphism, made possible by inheritance.

@Override is one of the most commonly used annotations in Java. It tells the compiler: "The method
below is intended to override a method from the superclass". If it does not actually override a
method, the compiler reports an error.

Example 3: Multilevel Inheritance


class Animal {
void breathe() { [Link]("Breathing..."); }
}

class Mammal extends Animal {


void walk() { [Link]("Walking..."); }
}

class Human extends Mammal {


void speak() { [Link]("Speaking..."); }
}

public class Prog3 {


public static void main(String[] args) {
Human h = new Human();
[Link](); // from Animal
[Link](); // from Mammal
[Link](); // Human's own
}
}

Output: Breathing...
Walking...
Speaking...
Human extends Mammal, which extends Animal, forming a chain. Human inherits members from every class
above it in the chain, not just its immediate parent.

Example 4: Hierarchical Inheritance


class Vehicle {
void start() { [Link]("Vehicle starting..."); }
}

class Car extends Vehicle { }


class Bike extends Vehicle { }

public class Main {


public static void main(String[] args) {
Car c = new Car();
Bike b = new Bike();
[Link]();
[Link]();
}
}

Output: Vehicle starting...


Vehicle starting...

Car and Bike are unrelated to each other, but both independently inherit start() from the same parent,
Vehicle. This is hierarchical inheritance.

Example 5: private Members Are Not Directly Inherited-Access


class Account {
private double balance = 1000;

double getBalance() { // public-ish access point


return balance;
}
}

class SavingsAccount extends Account {


void show() {
// [Link](balance); // COMPILE ERROR: balance is private in Account
[Link]("Balance: " + getBalance()); // OK, via inherited method
}
}

public class Main {


public static void main(String[] args) {
SavingsAccount s = new SavingsAccount();
[Link]();
}
}

Output: Balance: 1000.0

SavingsAccount cannot touch balance directly because it is private to Account, but it can still reach it
indirectly through the inherited method getBalance() — private fields exist in the child object but are hidden
behind the parent's access rules.
2. Method Overriding

Method overriding happens when a subclass provides its own implementation of a method that is already
defined in its superclass, using exactly the same method name, same parameter list, and a compatible return
type. It is called runtime (dynamic) polymorphism, because Java decides, while the program is actually
running, which version of the method to execute — based on the real (actual) type of the object, not the
type of the reference variable pointing to it.
Rules that MUST be followed for a valid override:
• Method name must be identical to the superclass method
• Parameter list (number, type, order) must be exactly identical — if it differs, it becomes overloading
instead, not overriding
• Return type must be the same
• Access modifier in the subclass cannot be more restrictive than in the superclass (e.g. cannot override a
public method with a private one)
• A method marked final, static, or private in the superclass CANNOT be overridden
• The @Override annotation is optional but strongly recommended — the compiler then checks that you
are truly overriding something, catching typos immediately

Overloading vs Overriding:
Overloading: SAME class, SAME name, DIFFERENT parameters, resolved at COMPILE time.
Overriding: PARENT/CHILD classes, SAME name, SAME parameters, resolved at RUN time.

Example 1: Basic Method Overriding


class Animal {
void makeSound() {
[Link]("Animal makes a generic sound");
}
}

class Dog extends Animal {


@Override
void makeSound() {
[Link]("Dog barks: Woof Woof");
}
}

public class Main {


public static void main(String[] args) {
Animal a = new Dog(); // parent reference, child object
[Link]();
}
}

Output: Dog barks: Woof Woof

Even though the reference type is Animal, Java looks at the ACTUAL object at runtime (a Dog), and calls
Dog's overridden version — not Animal's. This runtime decision is the core idea of dynamic polymorphism.

Example 2: Runtime Polymorphism With an Array of Different Subclasses


class Shape {
double area() { return 0; }
void describe() { [Link]("Area = " + area()); }
}
class Circle extends Shape {
double radius = 4;
@Override
double area() { return [Link] * radius * radius; }
}

class Square extends Shape {


double side = 5;
@Override
double area() { return side * side; }
}

public class Main {


public static void main(String[] args) {
Shape[] shapes = { new Circle(), new Square() };
for (Shape s : shapes) {
[Link](); // calls the correct overridden area() for each object
}
}
}

Output: Area = 50.26548245743669


Area = 25.0

describe() is written once, in Shape, calling area(). Yet each object in the array runs its OWN overridden
area() — Circle's or Square's — automatically, without describe() needing any if/else checks for the object's
type.

Example 3: Using [Link]() to Extend (Not Replace) the Parent's Behaviour


class Employee {
void work() {
[Link]("Employee performs general duties");
}
}

class Manager extends Employee {


@Override
void work() {
[Link](); // still run the parent's original behaviour
[Link]("Manager also conducts team meetings");
}
}

public class Main {


public static void main(String[] args) {
Employee e = new Manager();
[Link]();
}
}

Output: Employee performs general duties


Manager also conducts team meetings

Overriding does not force you to throw away the parent's logic. [Link]() calls Employee's original
version first, and Manager then adds its own extra behaviour on top of it.

Example 4: final Method Cannot Be Overridden (Invalid Override)


class Vehicle {
final void showLicense() {
[Link]("Standard license check for all vehicles.");
}
}

class Car extends Vehicle {


// void showLicense() { ... }
// COMPILE ERROR if uncommented:
// "showLicense() in Car cannot override final method in Vehicle"
}

public class Main {


public static void main(String[] args) {
new Car().showLicense();
}
}

Output: Standard license check for all vehicles.

Vehicle deliberately marks showLicense() as final specifically to PREVENT overriding — guaranteeing that
every subclass, including Car, always uses exactly the same implementation, with no exceptions.

Example 5: Overriding vs Overloading Side by Side


class Printer {
// OVERLOADING: same class, same name, DIFFERENT parameters
void print(String s) { [Link]("Printing text: " + s); }
void print(int n) { [Link]("Printing number: " + n); }
}

class ColorPrinter extends Printer {


// OVERRIDING: parent/child, same name, SAME parameters
@Override
void print(String s) {
[Link]("Printing in COLOR: " + s);
}
}

public class Main {


public static void main(String[] args) {
Printer p = new ColorPrinter();
[Link]("Report"); // overridden version runs (runtime decision)
[Link](101); // only overloaded version exists, inherited as-is
}
}

Output: Printing in COLOR: Report


Printing number: 101

print(String) is overridden by ColorPrinter, so the child's version runs. print(int) was never touched by
ColorPrinter, so the original, inherited (overloaded) version from Printer runs unchanged.

Changing the parameter list even slightly (e.g. area(double r) in the parent vs area(int r) in the child) does
NOT override the method — it silently creates a brand new OVERLOADED method instead, and the parent's
original method remains completely untouched. Always add @Override so the compiler catches this mistake
immediately.
3. The super Keyword

super is a reference used inside a subclass to refer to its immediate parent class. It has three main uses:
• super() — calls the parent class's constructor. Must be the first statement in a subclass constructor. If a
subclass constructor does not explicitly call super(...), Java silently inserts a call to the parent's no-
argument constructor as the first line.
• [Link]() — calls the parent class's version of a method that the subclass has overridden, when
the overridden behaviour still needs to run as part of the new behaviour.
• [Link] — accesses a parent class's field when the subclass has a field with the same name (field
hiding), to remove ambiguity.

‘this’ refers to the current object; ‘super’ refers to the parent part of the current object. They are used very
similarly, but this()/super() can each appear only as the very first statement of a constructor, and never both
together.

Example 1: super() Calling the Parent Constructor Explicitly


class Vehicle {
String type;

Vehicle(String type) {
[Link] = type;
[Link]("Vehicle constructor: " + type);
}
}

class Bike extends Vehicle {


Bike() {
super("Two-Wheeler"); // must be the first line
[Link]("Bike constructor finished");
}
}

public class Prog4 {


public static void main(String[] args) {
Bike b = new Bike();
}
}

Output: Vehicle constructor: Two-Wheeler


Bike constructor finished

super("Two-Wheeler") explicitly invokes Vehicle's constructor before Bike's own body runs, ensuring the
inherited part of the object is initialised first.

Example 2: The Implicit super() Call


class Animal {
Animal() {
[Link]("Animal constructor runs (implicitly called)");
}
}

class Dog extends Animal {


Dog() {
// no explicit super() written here...
[Link]("Dog constructor runs");
}
}
public class Prog5 {
public static void main(String[] args) {
Dog d = new Dog();
}
}

Output: Animal constructor runs (implicitly called)


Dog constructor runs

Even though Dog's constructor never writes super(), Java automatically inserts a call to Animal's no-
argument constructor as the very first (hidden) line — this is why 'Animal constructor runs' always prints
first.

Example 3: [Link]() Calling an Overridden Parent Method


class Employee {
void work() {
[Link]("Employee performs general duties");
}
}

class Manager extends Employee {


@Override
void work() {
[Link](); // run the parent's version first
[Link]("Manager also conducts team meetings");
}
}

public class Main {


public static void main(String[] args) {
Manager m = new Manager();
[Link]();
}
}

Output: Employee performs general duties


Manager also conducts team meetings

Manager overrides work(), but still wants the original Employee behaviour to run too. [Link]() explicitly
invokes the parent's version before adding Manager-specific behaviour, instead of throwing it away entirely.

Example 4: [Link] Resolving a Field Naming Conflict


class Shape {
String color = "undefined";
}

class Square extends Shape {


String color = "red"; // hides (shadows) Shape's 'color' field

void show() {
[Link]("Square's color: " + color);
[Link]("Shape's color: " + [Link]);
}
}

public class Main {


public static void main(String[] args) {
new Square().show();
}
}
Output: Square's color: red
Shape's color: undefined

Both classes declare a field named color. Inside Square, plain color refers to Square's own field, while
[Link] explicitly reaches into the parent Shape's field, resolving the naming conflict.

Writing code before super(...) in a constructor causes a compile error: 'call to super must be first statement
in constructor'.
4. Abstract Classes

An abstract class is a class declared with the abstract keyword that cannot be instantiated directly — you can
never write new SomeAbstractClass(). It exists purely to be extended, acting as a partially-complete
template that forces subclasses to fill in specific details.
An abstract class can freely mix:
• Ordinary, fully-implemented methods (with a method body), which are simply inherited as-is
• Abstract methods (declared but with no body — see Topic 5), which every concrete subclass MUST
override
• Fields, constructors, and static methods, exactly like a normal class
A class that extends an abstract class must either implement every one of its abstract methods, or itself be
declared abstract (deferring the obligation further down the hierarchy).

Key Idea
Use an abstract class when related classes share some common code (put it in the abstract class) but each
must also implement some behaviour uniquely (make it abstract). It answers 'what must every subclass be
able to do', while still letting you share reusable code.

4.2 Example Programs


Example 1: An Abstract Class Cannot Be Instantiated
abstract class Shape {
void info() {
[Link]("I am a shape.");
}
}

public class Main {


public static void main(String[] args) {
// Shape s = new Shape(); // COMPILE ERROR: Shape is abstract; cannot be instantiated
Shape s = new Circle(); // OK: via a concrete subclass
[Link]();
}
}

class Circle extends Shape { }

Output: I am a shape.

Shape is abstract, so new Shape() is illegal. However, its ordinary method info() is still fully usable through
any concrete subclass, such as Circle.

Example 2: Mixing Concrete and Abstract Methods


abstract class Employee {
String name;

Employee(String name) {
[Link] = name;
}

void checkIn() { // concrete: shared by every employee


[Link](name + " checked in.");
}
abstract double calculateSalary(); // abstract: every subclass differs
}

class Manager extends Employee {


Manager(String name) { super(name); }

@Override
double calculateSalary() { return 80000; }
}

public class Main {


public static void main(String[] args) {
Manager m = new Manager("Divya");
[Link](); // inherited, concrete
[Link]("Salary: " + [Link]()); // subclass-specific
}
}

Output: Divya checked in.


Salary: 80000.0

checkIn() is shared, ready-made code, written once in Employee. calculateSalary() has no sensible single
answer for all employees, so it is left abstract, and Manager supplies its own version.

Example 3: A Subclass That Fails to Implement All Abstract Methods Must Also Be Abstract
abstract class Vehicle {
abstract void start();
abstract void stop();
}

abstract class Car extends Vehicle { // implements only ONE method


@Override
void start() {
[Link]("Car starting...");
}
// stop() is still not implemented, so Car MUST remain abstract
}

class Sedan extends Car {


@Override
void stop() {
[Link]("Sedan stopping...");
}
}

public class Main {


public static void main(String[] args) {
Vehicle v = new Sedan();
[Link]();
[Link]();
}
}

Output: Car starting...


Sedan stopping...

Car only implements start(), leaving stop() unimplemented, so Car itself must stay abstract. Only Sedan,
which implements the remaining method stop(), becomes concrete and instantiable.

Example 4: Abstract Class With a Constructor (Used via super())


abstract class Account {
double balance;

Account(double balance) { // abstract classes CAN have constructors


[Link] = balance;
[Link]("Account created with balance " + balance);
}

abstract void applyInterest();


}

class SavingsAccount extends Account {


SavingsAccount(double balance) {
super(balance);
}

@Override
void applyInterest() {
balance += balance * 0.04;
[Link]("Interest applied. New balance: " + balance);
}
}

public class Main {


public static void main(String[] args) {
SavingsAccount acc = new SavingsAccount(1000);
[Link]();
}
}

Output: Account created with balance 1000.0


Interest applied. New balance: 1040.0

'Abstract class with zero abstract methods' is legal in Java — it simply cannot be instantiated, even though every
method has a body. This is sometimes used to intentionally prevent direct object creation of a base class.

You might also like