Subclass / Superclass

บทนำ: ความสัมพันธ์ระหว่าง Parent-Child Classes

เมื่อเราใช้ inheritance ชื่อเรียกจะเปลี่ยน – class ที่ให้ความสามารถ เรียกว่า Superclass (หรือ Parent Class) และ class ที่รับความสามารถ เรียกว่า Subclass (หรือ Child Class)

text┌──────────────────────┐
│   Superclass / Parent│
│   (ให้ความสามารถ)    │
└──────────────────────┘
          △
          │ extends
          │
    ┌─────┴─────┐
    │           │
┌─────────┐ ┌─────────┐
│ Subclass│ │ Subclass│
│ (Child) │ │ (Child) │
└─────────┘ └─────────┘

Terminology: Superclass vs Subclass

คำศัพท์ที่ต้องรู้

textSuperclass = Parent Class = Base Class
└─ class ที่ปล่อยความสามารถให้
└─ class ที่อยู่สูงสุดในลำดับชั้น

Subclass = Child Class = Derived Class
└─ class ที่รับความสามารถมา
└─ class ที่อยู่ล่างในลำดับชั้น

ตัวอย่างที่ 1: สำรวจ Superclass และ Subclass

มาเขียน code ที่แสดงให้เห็นความสัมพันธ์ระหว่าง superclass และ subclass

java// SUPERCLASS (Parent/Base Class)
public class Vehicle {
    private String brand;
    private int year;
    
    public Vehicle(String brand, int year) {
        this.brand = brand;
        this.year = year;
    }
    
    public String getBrand() {
        return this.brand;
    }
    
    public void start() {
        System.out.println("Vehicle is starting...");
    }
    
    public void stop() {
        System.out.println("Vehicle is stopping...");
    }
    
    public void displayInfo() {
        System.out.printf("Brand: %s | Year: %d\n", brand, year);
    }
}

// SUBCLASS 1 (Child Class)
public class Car extends Vehicle {
    private int numberOfDoors;
    
    public Car(String brand, int year, int doors) {
        super(brand, year);           // เรียก superclass constructor
        this.numberOfDoors = doors;
    }
    
    public int getNumberOfDoors() {
        return this.numberOfDoors;
    }
    
    public void displayInfo() {
        super.displayInfo();          // เรียก superclass method
        System.out.println("Doors: " + numberOfDoors);
    }
}

// SUBCLASS 2 (Child Class)
public class Motorcycle extends Vehicle {
    private boolean hasSidecar;
    
    public Motorcycle(String brand, int year, boolean sidecar) {
        super(brand, year);           // เรียก superclass constructor
        this.hasSidecar = sidecar;
    }
    
    public void displayInfo() {
        super.displayInfo();          // เรียก superclass method
        System.out.println("Has sidecar: " + hasSidecar);
    }
}

// ใช้งาน
public class Main {
    public static void main(String[] args) {
        // Superclass object
        System.out.println("=== Superclass ===");
        Vehicle vehicle = new Vehicle("Generic", 2024);
        vehicle.displayInfo();
        vehicle.start();
        
        // Subclass 1 object
        System.out.println("\n=== Subclass 1: Car ===");
        Car car = new Car("Toyota", 2024, 4);
        car.displayInfo();
        car.start();       // Inherited from Vehicle
        
        // Subclass 2 object
        System.out.println("\n=== Subclass 2: Motorcycle ===");
        Motorcycle motorcycle = new Motorcycle("Harley", 2024, true);
        motorcycle.displayInfo();
        motorcycle.start();  // Inherited from Vehicle
    }
}

Output:

text=== Superclass ===
Brand: Generic | Year: 2024
Vehicle is starting...

=== Subclass 1: Car ===
Brand: Toyota | Year: 2024
Doors: 4
Vehicle is starting...

=== Subclass 2: Motorcycle ===
Brand: Harley | Year: 2024
Has sidecar: true
Vehicle is starting...

คำอธิบาย:

  • Vehicle คือ superclass – เก็บความสามารถที่เหมือนกัน
  • Car และ Motorcycle คือ subclass – สืบทอดจาก Vehicle
  • Subclass สามารถใช้ methods (start()stop()) จาก superclass ได้
  • super.displayInfo() เรียก superclass method ก่อน แล้ว subclass เพิ่มข้อมูลเองต่อ

ลำดับชั้นของ Subclass/Superclass

Single-Level Inheritance

text┌──────────────┐
│  Superclass  │
│   (Vehicle)  │
└──────────────┘
        △
        │ extends
        │
    ┌───┴──────────┐
    │              │
┌────────┐   ┌────────────┐
│  Car   │   │ Motorcycle │
│(Subclass) (Subclass)   │
└────────┘   └────────────┘

Multi-Level Inheritance

text┌──────────────┐
│   Vehicle    │  ← Superclass level 1
│ (Superclass) │
└──────────────┘
        △
        │ extends
        │
    ┌───────────┐
    │    Car    │  ← Superclass level 2 (for SportsCar)
    │(Subclass) │    Subclass level 1 (for Vehicle)
    └───────────┘
        △
        │ extends
        │
    ┌────────────┐
    │ SportsCar  │  ← Subclass level 2
    │ (Subclass) │
    └────────────┘

ตัวอย่างที่ 2: Multi-Level Subclass/Superclass

java// LEVEL 1: Superclass
public class Animal {
    protected String name;
    
    public Animal(String name) {
        this.name = name;
    }
    
    public void eat() {
        System.out.println(name + " is eating");
    }
    
    public void sleep() {
        System.out.println(name + " is sleeping");
    }
}

// LEVEL 2: Subclass of Animal, Superclass of Dog
public class Mammal extends Animal {
    protected String furColor;
    
    public Mammal(String name, String furColor) {
        super(name);
        this.furColor = furColor;
    }
    
    public void nurseBaby() {
        System.out.println(name + " is nursing baby");
    }
    
    public void displayInfo() {
        System.out.printf("Name: %s | Fur: %s\n", name, furColor);
    }
}

// LEVEL 3: Subclass of Mammal
public class Dog extends Mammal {
    private String breed;
    
    public Dog(String name, String furColor, String breed) {
        super(name, furColor);
        this.breed = breed;
    }
    
    public void bark() {
        System.out.println(name + " says: Woof!");
    }
    
    public void displayInfo() {
        super.displayInfo();
        System.out.println("Breed: " + breed);
    }
}

// ใช้งาน
public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog("Rex", "Brown", "Husky");
        
        System.out.println("=== Dog Information ===");
        dog.displayInfo();
        
        System.out.println("\n=== Dog Actions ===");
        dog.eat();           // From Animal (superclass level 1)
        dog.sleep();         // From Animal (superclass level 1)
        dog.nurseBaby();     // From Mammal (superclass level 2)
        dog.bark();          // From Dog (itself)
    }
}

Output:

text=== Dog Information ===
Name: Rex | Fur: Brown
Breed: Husky

=== Dog Actions ===
Rex is eating
Rex is sleeping
Rex is nursing baby
Rex says: Woof!

คำอธิบาย:

  • Dog → Mammal → Animal (hierarchy)
  • Dog เป็น subclass ของ Mammal
  • Mammal เป็น superclass ของ Dog และ subclass ของ Animal
  • Dog สามารถใช้ methods จากทั้ง Animal และ Mammal

Differences: Superclass vs Subclass

ตารางเปรียบเทียบ

text┌─────────────────┬──────────────────────┬──────────────────────┐
│                 │ Superclass           │ Subclass             │
├─────────────────┼──────────────────────┼──────────────────────┤
│ หน้าที่         │ ให้ความสามารถ       │ รับและขยายความสามารถ│
│ Scope           │ กว้าง (general)      │ แคบ (specific)       │
│ Code            │ Base functionality   │ เพิ่มเติม base code  │
│ Methods         │ ทั้งหมด public      │ บาง methods override │
│ Extends         │ ไม่มี extends       │ extends superclass   │
│ ตัวอย่าง       │ Vehicle              │ Car, Motorcycle      │
└─────────────────┴──────────────────────┴──────────────────────┘

Relationship: “IS-A”

Subclass “IS-A” Superclass

textความสัมพันธ์:
└─ Car IS-A Vehicle
└─ Dog IS-A Animal
└─ Manager IS-A Employee
└─ SportsCar IS-A Car

ทดสอบ:
└─ "Dog is an Animal?" → YES ✓
└─ "Car is a Vehicle?" → YES ✓
└─ "Engine is a Car?" → NO ✗ (ไม่ควรใช้ inheritance)

ตัวอย่างที่ 3: Real-World Scenario

java// SUPERCLASS
public class Shape {
    protected String color;
    
    public Shape(String color) {
        this.color = color;
    }
    
    public String getColor() {
        return this.color;
    }
    
    public void displayColor() {
        System.out.println("Color: " + color);
    }
}

// SUBCLASS 1
public class Rectangle extends Shape {
    private double width;
    private double height;
    
    public Rectangle(String color, double width, double height) {
        super(color);
        this.width = width;
        this.height = height;
    }
    
    public double getArea() {
        return width * height;
    }
    
    public void displayInfo() {
        displayColor();  // From superclass
        System.out.printf("Rectangle: %.2f x %.2f = %.2f\n", 
                         width, height, getArea());
    }
}

// SUBCLASS 2
public class Circle extends Shape {
    private double radius;
    
    public Circle(String color, double radius) {
        super(color);
        this.radius = radius;
    }
    
    public double getArea() {
        return Math.PI * radius * radius;
    }
    
    public void displayInfo() {
        displayColor();  // From superclass
        System.out.printf("Circle: radius=%.2f, area=%.2f\n", 
                         radius, getArea());
    }
}

// SUBCLASS 3: Multi-level
public class Cube extends Rectangle {
    private double depth;
    
    public Cube(String color, double side, double depth) {
        super(color, side, side);
        this.depth = depth;
    }
    
    public double getVolume() {
        return getArea() * depth;
    }
    
    public void displayInfo() {
        super.displayInfo();
        System.out.printf("Cube: volume=%.2f\n", getVolume());
    }
}

// ใช้งาน
public class Main {
    public static void main(String[] args) {
        Rectangle rect = new Rectangle("Red", 5, 10);
        rect.displayInfo();
        
        System.out.println();
        
        Circle circle = new Circle("Blue", 7);
        circle.displayInfo();
        
        System.out.println();
        
        Cube cube = new Cube("Green", 3, 3);
        cube.displayInfo();
    }
}

Output:

textColor: Red
Rectangle: 5.00 x 10.00 = 50.00

Color: Blue
Circle: radius=7.00, area=153.94

Color: Green
Rectangle: 3.00 x 3.00 = 9.00
Cube: volume=27.00

คำอธิบาย:

  • Shape เป็น superclass ของ Rectangle และ Circle
  • Rectangle เป็น superclass ของ Cube
  • ทั้ง subclass สามารถใช้ displayColor() จาก superclass ได้
  • Cube สามารถใช้ getArea() จาก Rectangle

ข้อควรระวัง: Superclass vs Subclass

1. Private Members ไม่ Inherit

javapublic class Parent {
    private String privateData;    // ← ไม่สามารถ access จาก child
    protected String protectedData; // ← สามารถ access จาก child
}

public class Child extends Parent {
    public void test() {
        // ❌ Cannot access privateData
        // System.out.println(privateData);
        
        // ✓ Can access protectedData
        System.out.println(protectedData);
    }
}

2. Constructor ไม่ Inherit (แต่ต้องเรียก super())

javapublic class Parent {
    public Parent(String name) {
        System.out.println("Parent constructor");
    }
}

public class Child extends Parent {
    public Child(String name) {
        super(name);  // ← ต้องเรียก parent constructor
    }
}

3. Static Members ไม่ Override (แต่ Inherit)

javapublic class Parent {
    public static void staticMethod() {
        System.out.println("Parent static");
    }
}

public class Child extends Parent {
    public static void staticMethod() {
        System.out.println("Child static");  // ← Shadowing, not overriding
    }
}

// ใช้งาน
Parent.staticMethod();      // "Parent static"
Child.staticMethod();       // "Child static"

Parent obj = new Child();
obj.staticMethod();         // "Parent static" (called via Parent reference)

Hierarchy Best Practices

1. Single Superclass

java// ✓ ดี: ชัดเจน
public class Dog extends Animal {
    // Dog extends only Animal
}

// ❌ Java ไม่อนุญาต: Multiple inheritance
// public class Dog extends Animal, Mammal {

2. Appropriate Naming

java// ✓ ชื่อชัดเจน
class Vehicle {}        // Superclass
class Car extends Vehicle {}      // Subclass
class SportsCar extends Car {}    // Sub-subclass

// ❌ ชื่อสับสน
class X {}
class Y extends X {}
class Z extends Y {}

3. ไม่ควร Extend เกิน 3-4 Levels

java// ✓ ดีพอ
A → B → C

// ⚠️ ซับซ้อนเกินไป
A → B → C → D → E → F

Type Compatibility

Subclass object สามารถ assign ให้ Superclass reference ได้

javaVehicle vehicle = new Car("Toyota", 2024, 4);
// ✓ ถูกต้อง: Subclass object → Superclass reference

Car car = new Vehicle();
// ❌ ผิด: Superclass object → Subclass reference

ตัวอย่างที่ 4: Type Compatibility

javapublic class Main {
    public static void main(String[] args) {
        // Car object
        Car car = new Car("Toyota", 2024, 4);
        
        // ✓ Assign to Vehicle reference (superclass)
        Vehicle vehicle = car;
        
        vehicle.displayInfo();  // ใช้ได้
        vehicle.start();        // ใช้ได้
        
        // ❌ ไม่สามารถ access Car-specific method ผ่าน Vehicle reference
        // vehicle.getNumberOfDoors();  // ERROR!
        
        // ✓ ต้อง cast กลับเป็น Car
        Car carAgain = (Car) vehicle;
        System.out.println("Doors: " + carAgain.getNumberOfDoors());
    }
}

public class Vehicle {
    private String brand;
    private int year;
    
    public Vehicle(String brand, int year) {
        this.brand = brand;
        this.year = year;
    }
    
    public void displayInfo() {
        System.out.printf("Brand: %s | Year: %d\n", brand, year);
    }
    
    public void start() {
        System.out.println("Vehicle is starting");
    }
}

public class Car extends Vehicle {
    private int numberOfDoors;
    
    public Car(String brand, int year, int doors) {
        super(brand, year);
        this.numberOfDoors = doors;
    }
    
    public int getNumberOfDoors() {
        return numberOfDoors;
    }
}

Output:

textBrand: Toyota | Year: 2024
Vehicle is starting
Doors: 4

คำอธิบาย:

  • Vehicle vehicle = car; – assign Car object ให้ Vehicle reference
  • ผ่าน vehicle reference สามารถใช้ Vehicle methods ได้
  • ต้อง cast กลับเป็น Car เพื่อเข้าถึง Car-specific methods

สรุป

Superclass และ Subclass เป็นศัพท์พื้นฐานในการเข้าใจ inheritance ที่ superclass คือ class ที่ให้ความสามารถ (เหมือนพ่อแม่) ในขณะที่ subclass คือ class ที่รับความสามารถนั้น (เหมือนลูก)

ความเข้าใจที่ลึกซึ้งเกี่ยวกับความสัมพันธ์นี้ช่วยให้เราออกแบบระบบ class ที่เหมาะสม เรา ต้องสร้าง superclass ที่มีคุณลักษณะร่วม ของหลาย objects และให้ subclass เพิ่มเติมหรือปรับแต่ง functionality ให้เหมาะสมกับตัวเอง

สิ่งสำคัญที่ต้องจำคือ ความสัมพันธ์ IS-A ต้องเป็นจริง เช่น “Dog IS-A Animal” และ ลำดับชั้นไม่ควรลึกเกินไป เพราะมันจะทำให้ code ซับซ้อนและยากต่อการดูแล เมื่อ subclass หรือ superclass ถูกออกแบบได้ดี inheritance จะกลายเป็นเครื่องมือที่ทรงพลังในการสร้าง code ที่มีโครงสร้างและสามารถนำกลับมาใช้ได้