08. Inheritance
Inheritance lets a child class **reuse and extend** the parent's structure and behavior with the `extends` keyword. This lecture covers `extends`, `super`, the `@Override` annotation, and method overriding.
What you'll learn
- 1Define a parent-child relationship with `extends`
- 2Call the parent constructor with `super(...)`
- 3Override methods correctly with `@Override`
- 4Understand single inheritance and the `Object` root class
- 5Block extension with `final`
Overview
Inheritance lets a child class **reuse and extend** the parent's structure and behavior with the `extends` keyword. This lecture covers `extends`, `super`, the `@Override` annotation, and method overriding.
Core Concepts
1) `extends`
class Animal {
String name;
Animal(String name) { this.name = name; }
void speak() { System.out.println(name + " makes a sound"); }
}
class Dog extends Animal {
Dog(String name) { super(name); }
@Override
void speak() { System.out.println(name + " says Woof!"); }
}- `Dog` inherits the fields and methods of `Animal`
- `super(name)` calls the parent constructor
- `@Override` lets the compiler verify you really are overriding
2) Method overriding
A child class can redefine a parent method **with the same signature**. At runtime, the actual object's implementation runs (polymorphism β covered in lecture 09).
3) `super`
class Child extends Parent {
@Override
void doWork() {
super.doWork(); // call parent's implementation
System.out.println("extra"); // then add child behavior
}
}4) `Object` root
Every class in Java implicitly inherits from `Object`. That's why every object has `toString()`, `equals()`, `hashCode()`.
5) `final` class / `final` method
- `final class X` prevents extension (e.g. `String`, `Integer`)
- `final` method prevents overriding
Examples
Example 1 β `AnimalDog.java`: basic inheritance and override
public class AnimalDog {
static class Animal {
String name;
Animal(String name) { this.name = name; }
void speak() { System.out.println(name + " makes a sound"); }
}
static class Dog extends Animal {
Dog(String name) { super(name); }
@Override
void speak() { System.out.println(name + " says Woof!"); }
}
public static void main(String[] args) {
Animal a = new Animal("Generic");
Dog d = new Dog("Rex");
a.speak();
d.speak();
}
}**Output**
Generic makes a sound
Rex says Woof!**Note:** without `@Override` a typo silently creates a brand-new method.
Example 2 β `SuperCall.java`: calling the parent first
public class SuperCall {
static class Base {
void log() { System.out.println("Base.log"); }
}
static class Sub extends Base {
@Override
void log() {
super.log();
System.out.println("Sub.log");
}
}
public static void main(String[] args) {
new Sub().log();
}
}**Output**
Base.log
Sub.log**Note:** `super.method()` invokes the parent's implementation explicitly.
Example 3 β `ObjectToString.java`: the `Object.toString` you always get
public class ObjectToString {
static class Point {
int x, y;
Point(int x, int y) { this.x = x; this.y = y; }
@Override
public String toString() { return "Point(" + x + "," + y + ")"; }
}
public static void main(String[] args) {
Point p = new Point(1, 2);
System.out.println(p); // calls toString implicitly
System.out.println("p = " + p); // toString again via +
}
}**Output**
Point(1,2)
p = Point(1,2)**Note:** override `toString` for human-readable debug output.
Example 4 β `FinalDemo.java`: blocking extension with `final`
public class FinalDemo {
static final class Sealed {
void hello() { System.out.println("hello"); }
}
// class Tries extends Sealed {} // compile error: cannot inherit from final
public static void main(String[] args) {
new Sealed().hello();
}
}**Output**
hello**Note:** the JDK uses `final` for value types like `String` / `Integer`.
Common Mistakes
- Forgetting `super(...)` when the parent has no no-arg constructor
- Misspelling a method name β it becomes a new method instead of an override (add `@Override`)
- Trying to extend a `final` class
- Confusing inheritance with composition β favor composition when behavior, not type, is shared
- Accessing `private` parent fields directly from a child (use `protected` or getters)
Summary
- Inherit with `extends`, call the parent with `super(...)`
- Override with the same signature; use `@Override` to be safe
- Java has **single inheritance** (one parent class, but multiple interfaces β lecture 10)
Practice
# Practice - 08. Inheritance
## Exercise 1 β `Shape` hierarchy
- File: `Homework01.java`
- Key concepts: `extends`, override `area()`
Requirements
- Parent class `Shape` with `String name` and `double area() { return 0; }`.
- Children `Rectangle(w, h)` and `Circle(r)` override `area()`.
- In main, store both in `Shape[]` and print each name + area.
Expected output
rect: 12.0
circle: 12.566## Exercise 2 β `Employee` / `Manager`
- File: `Homework02.java`
- Key concepts: `super`, field reuse
Requirements
- Class `Employee(String name, long salary)` with `String describe()` β `name(salary)`.
- Class `Manager(String name, long salary, int teamSize) extends Employee` overrides `describe()` to append ` team=N`.
Expected output
Jisoo(3000000)
Minsu(5000000) team=4## Solutions After trying it yourself, compare with [`answer/`](./answer/).
Solution code (homework/answer/)
answer/Homework01.java
/** Shape hierarchy. */
public class Homework01 {
public static void main(String[] args) {
Shape[] shapes = { new Rectangle(3, 4), new Circle(2) };
for (Shape s : shapes) System.out.printf("%s: %.3f%n", s.name, s.area());
}
}
class Shape {
String name;
Shape(String name) { this.name = name; }
double area() { return 0; }
}
class Rectangle extends Shape {
double w, h;
Rectangle(double w, double h) { super("rect"); this.w = w; this.h = h; }
@Override double area() { return w * h; }
}
class Circle extends Shape {
double r;
Circle(double r) { super("circle"); this.r = r; }
@Override double area() { return Math.PI * r * r; }
}
answer/Homework02.java
/** Employee / Manager. */
public class Homework02 {
public static void main(String[] args) {
System.out.println(new Employee("Jisoo", 3_000_000).describe());
System.out.println(new Manager("Minsu", 5_000_000, 4).describe());
}
}
class Employee {
String name; long salary;
Employee(String name, long salary) { this.name = name; this.salary = salary; }
String describe() { return name + "(" + salary + ")"; }
}
class Manager extends Employee {
int teamSize;
Manager(String name, long salary, int teamSize) {
super(name, salary);
this.teamSize = teamSize;
}
@Override
String describe() { return super.describe() + " team=" + teamSize; }
}
Try It Yourself
cd 02_oop/08_inheritance/src
javac AnimalDog.java
java AnimalDogNext Lecture
[09_Polymorphism](../09_λ€νμ±/) β parent-reference / child-object, `instanceof`, pattern matching.
All lecture materials and example code are openly available on GitHub.
View on GitHub β