Java + Spring Boot track

Lesson 08 · Part 2: Object-Oriented Programming

Inheritance

Inheritance is an OOP mechanism that defines a new class by inheriting the fields and methods of an existing class. Common operations determined by the parent (super)…

Part 2: Object-Oriented Programming4 min readFree lesson

Inheritance is an OOP mechanism that defines a new class by inheriting the fields and methods of an existing class. Common operations determined by the parent (super) can be used as is in the child (sub) or only some of them can be redefined (@Override), reducing code duplication.

Learning Objectives

  • Inherit the class as extends
  • Call the parent constructor with super(...)
  • Know the role of @Override annotation
  • Know the meaning of final of-class/method
  • I know that protected has limited access open only to children.

Key concepts

1) extends and parent-child relationship

class Animal {
    String name;
    Animal(String name) { this.name = name; }
    void speak() { System.out.println(name + ": ..."); }
}

class Dog extends Animal {
    Dog(String name) { super(name); }
    @Override
    void speak() { System.out.println(name + ": Woof woof!"); }
}

Java only allows single inheritance. A class can have at most one parent.

2) super keyword

  • In the constructor, super(...) calls the parent constructor (must be the first line!)
  • Within the method, super.method() calls the overridden parent method.

3) @Override

This annotation informs the compiler that the method to be overridden actually exists in the parent and is verified. Always attaching is recommended.

4) final

  • final class: Can no longer be inherited
  • final method: Overriding is not possible in children.
  • final field: cannot be changed once initialized

5) protected

protected members can be accessed from the same package + child classes. Wider than private and narrower than public.

See as example

Example 1 — Animal.java + Dog.java: The most basic inheritance

Animal.java:

public class Animal {
    protected String name;

    public Animal(String name) { this.name = name; }

    public void speak() {
        System.out.println(name + ": (default cry)");
    }
}

Dog.java:

public class Dog extends Animal {
    public Dog(String name) { super(name); }

    @Override
    public void speak() {
        System.out.println(name + ": Woof woof!");
    }

    public static void main(String[] args) {
        Animal a = new Animal("animal");
        Dog d = new Dog("Baduki");
        a.speak();
        d.speak();
    }
}

Execution result

Animal: (default cry)
Baduki: Woof!

Note: Dog uses the name field of Animal (accessible as protected).

Example 2 — SuperKeyword.java : Utilizing super

class Base {
    String tag() { return "[BASE]"; }
}

public class SuperKeyword extends Base {
    @Override
    String tag() {
        return super.tag() + " + " + "[SUB]";
    }

    public static void main(String[] args) {
        System.out.println(new SuperKeyword().tag());
    }
}

Execution result

[BASE] + [SUB]

Note: super.method() is useful when you want a child to extend a parent method.

Example 3 — FinalDemo.java: Inheritance/redefinition blocking

public class FinalDemo {
    static final class Constants {
        static final double PI = 3.141592;
    }

    static class Base {
        final void fixed() { System.out.println("No override"); }
        void open() { System.out.println("Base.open"); }
    }

    static class Sub extends Base {
        @Override
        void open() { System.out.println("Sub.open"); }
        //void fixed() { ... } // Compilation error: final method overriding prohibited
    }

    public static void main(String[] args) {
        Sub s = new Sub();
        s.fixed();
        s.open();
        System.out.println("PI=" + Constants.PI);
    }
}

Execution result

No override
Sub.open
PI=3.141592

Note: final is used when you want to intentionally break inheritance.

Example 4 — MethodOverride.java: Various children

class Shape {
    double area() { return 0.0; }
}

class Square extends Shape {
    double side;
    Square(double s) { this.side = s; }
    @Override double area() { return side * side; }
}

class Circle extends Shape {
    double radius;
    Circle(double r) { this.radius = r; }
    @Override double area() { return Math.PI * radius * radius; }
}

public class MethodOverride {
    public static void main(String[] args) {
        Shape[] shapes = { new Square(3), new Circle(2) };
        for (Shape s : shapes) {
            System.out.printf("area=%.3f%n", s.area());
        }
    }
}

Execution result

area=9.000
area=12.566

Note: If you call the same method with child objects in an array of parent types, the results will be different for each — just a taste of polymorphism (next section).

Common Mistakes

  1. Violating the rule that the parent constructor call must be the first line of the constructor.
  2. @Override was omitted and the signature was slightly different, resulting in overloading (quiet bug)
  3. Misunderstanding that you are overriding the private method (actually it is a new method)
  4. Unreasonable inheritance (extends even though it is not an is-a relationship)
  5. Deep inheritance hierarchy → reduced readability; Usually within 2~3 steps is recommended

Cleanup

  • Inheritance is the basis for code reuse + polymorphism
  • It is safe to attach @Override unconditionally.
  • Intentional blocking possible with final
  • composition is often a more flexible alternative to inheritance

Try it yourself

cd 02_object-oriented/08_inheritance/src
javac Animal.java Dog.java
java Dog

Example files

The runnable files used in this lesson. Copy them into your own project and experiment.

src/Animal.javaJava
public class Animal {
    protected String name;

    public Animal(String name) { this.name = name; }

    public void speak() {
        System.out.println(name + ": (default cry)");
    }
}
src/Dog.javaJava
public class Dog extends Animal {
    public Dog(String name) { super(name); }

    @Override
    public void speak() {
        System.out.println(name + ": Woof woof!");
    }

    public static void main(String[] args) {
        Animal a = new Animal("animal");
        Dog d = new Dog("Baduki");
        a.speak();
        d.speak();
    }
}
src/FinalDemo.javaJava
public class FinalDemo {
    static final class Constants {
        static final double PI = 3.141592;
    }

    static class Base {
        final void fixed() { System.out.println("No override"); }
        void open() { System.out.println("Base.open"); }
    }

    static class Sub extends Base {
        @Override
        void open() { System.out.println("Sub.open"); }
    }

    public static void main(String[] args) {
        Sub s = new Sub();
        s.fixed();
        s.open();
        System.out.println("PI=" + Constants.PI);
    }
}
src/MethodOverride.javaJava
class Shape {
    double area() { return 0.0; }
}

class Square extends Shape {
    double side;
    Square(double s) { this.side = s; }
    @Override double area() { return side * side; }
}

class Circle extends Shape {
    double radius;
    Circle(double r) { this.radius = r; }
    @Override double area() { return Math.PI * radius * radius; }
}

public class MethodOverride {
    public static void main(String[] args) {
        Shape[] shapes = { new Square(3), new Circle(2) };
        for (Shape s : shapes) {
            System.out.printf("area=%.3f%n", s.area());
        }
    }
}
src/SuperKeyword.javaJava
class Base {
    String tag() { return "[BASE]"; }
}

public class SuperKeyword extends Base {
    @Override
    String tag() {
        return super.tag() + " + " + "[SUB]";
    }

    public static void main(String[] args) {
        System.out.println(new SuperKeyword().tag());
    }
}

Assignment

Problem 1 — Employee and Manager

  • File name: Homework01.java
  • Core concepts: extends, super, method overriding

Requirements

  • Parent Employee(name, salary) + report() outputs in Hong Gil-dong's monthly salary is 3000000 format.
  • The child Manager(name, salary, bonus) overrides report() to output the total amount including bonus.
  • Call both from main.

Expected output

Hong Gil-dong's monthly salary is 3000000
Manager Kim's salary 5,000,000 + bonus 1,000,000 = 6,000,000

Problem 2 — Shape layer

  • File name: Homework02.java
  • Core Concept: Common Parent + Overriding + @Override

Requirements

  • Method double area() on parent Shape (returns 0.0).
  • The children Square and Triangle each override area().
  • Output the area in Shape[] array.

Expected output

Square: 9.0
Triangle: 6.0

Check the correct answer

After solving it yourself, compare it with the reference solution below.

Show the reference solution

Try the assignment yourself first — comparing your attempt with a working solution is where most of the learning happens.

Homework01.javaJava
/** Employee and Manager inheritance.*/
public class Homework01 {
    public static void main(String[] args) {
        Employee e = new Employee("Hong Gil-dong", 3_000_000);
        Manager m = new Manager("Manager Kim", 5_000_000, 1_000_000);
        e.report();
        m.report();
    }
}

class Employee {
    protected String name;
    protected long salary;

    Employee(String name, long salary) {
        this.name = name;
        this.salary = salary;
    }

    void report() {
        System.out.println(name + "salary" + salary);
    }
}

class Manager extends Employee {
    private long bonus;

    Manager(String name, long salary, long bonus) {
        super(name, salary);
        this.bonus = bonus;
    }

    @Override
    void report() {
        System.out.println(name + "salary" + salary + "+ bonus" + bonus
                + " = " + (salary + bonus));
    }
}
Homework02.javaJava
/** Shape layer area.*/
public class Homework02 {
    public static void main(String[] args) {
        ShapeHW[] shapes = { new SquareHW(3), new TriangleHW(4, 3) };
        for (ShapeHW s : shapes) {
            System.out.println(s.getClass().getSimpleName().replace("HW", "")
                    + ": " + s.area());
        }
    }
}

class ShapeHW {
    double area() { return 0.0; }
}

class SquareHW extends ShapeHW {
    double side;
    SquareHW(double s) { this.side = s; }
    @Override double area() { return side * side; }
}

class TriangleHW extends ShapeHW {
    double base, height;
    TriangleHW(double base, double height) { this.base = base; this.height = height; }
    @Override double area() { return base * height / 2.0; }
}

Learn this lesson with a mentor

Work through the Java + Spring Boot track on your own, or join a guided cohort at our Pitampura campus and online.

Call NowEnroll Now