บทนำ: ปัญหาของการทำซ้ำ Code
เมื่อเราเขียนโปรแกรม บ่อยครั้งที่เรามี classes ที่คล้ายกัน และ มี code ที่ซ้ำกัน
java// ❌ ปัญหา: Code ซ้ำซ้อน
public class Student {
private String name;
private String email;
private String studentID;
public Student(String name, String email, String studentID) {
this.name = name;
this.email = email;
this.studentID = studentID;
}
public void displayInfo() {
System.out.printf("Name: %s | Email: %s\n", name, email);
}
}
public class Teacher {
private String name;
private String email;
private String teacherID;
public Teacher(String name, String email, String teacherID) {
this.name = name;
this.email = email;
this.teacherID = teacherID;
}
public void displayInfo() {
System.out.printf("Name: %s | Email: %s\n", name, email);
}
}
ปัญหา:
- ❌
name,emailซ้ำกัน - ❌ Constructor logic ซ้ำกัน
- ❌
displayInfo()เกือบเหมือนกัน - ❌ ถ้าแก้ bug → ต้องแก้ทั้ง class!
- บทนำ: ปัญหาของการทำซ้ำ Code
- Inheritance คืออะไร?
- Inheritance Syntax
- การประกาศ
- ตัวอย่างที่ 1: Simple Inheritance
- What Gets Inherited?
- สิ่งที่สืบทอดได้
- ตัวอย่างที่ 2: Inheritance ด้วย Protected
- Constructor Chaining ใน Inheritance
- ทำไมต้อง super()?
- ตัวอย่างที่ 3: Multi-level Inheritance
- ตัวอย่างที่ 4: Inheritance ด้วย Business Logic
- IS-A Relationship
- Inheritance ใช้เมื่อมี "IS-A" ความสัมพันธ์
- ตัวอย่างที่ 5: IS-A vs HAS-A
- Benefits ของ Inheritance
- Best Practices: Inheritance
- 1. ใช้ Inheritance สำหรับ IS-A เท่านั้น
- 2. ไม่ควร Extend มากเกินไป
- 3. ใช้ super() เพื่อเรียก Parent Constructor
- 4. Protected > Public สำหรับ Internal Data
- สรุป
Inheritance คืออะไร?
Inheritance (สืบทอด) = Class หนึ่งสามารถ “สืบทอด” (inherit) properties และ methods จาก class อื่น
textConcept:
┌──────────────────────┐
│ Person (Parent) │
│ ───────────────── │
│ - name │
│ - email │
│ + displayInfo() │
└──────────────────────┘
△
│ (สืบทอด)
│
┌───┴────┐
│ │
┌─────────┐ ┌────────┐
│ Student │ │ Teacher│
│ (Child) │ │ (Child)│
└─────────┘ └────────┘
Inheritance Syntax
การประกาศ
java// Syntax:
public class ChildClass extends ParentClass {
// Child-specific code
}
// ตัวอย่าง:
public class Student extends Person {
// Student inherits from Person
}
public class Teacher extends Person {
// Teacher inherits from Person
}
ตัวอย่างที่ 1: Simple Inheritance
มาเขียน code ที่ใช้การสืบทอด เพื่อหลีกเลี่ยงการทำซ้ำ
java// Parent Class
public class Person {
private String name;
private String email;
public Person(String name, String email) {
this.name = name;
this.email = email;
}
public String getName() {
return this.name;
}
public String getEmail() {
return this.email;
}
public void displayInfo() {
System.out.printf("Name: %s | Email: %s\n", name, email);
}
}
// Child Class 1
public class Student extends Person {
private String studentID;
public Student(String name, String email, String studentID) {
super(name, email); // ← เรียก parent constructor
this.studentID = studentID;
}
public String getStudentID() {
return this.studentID;
}
}
// Child Class 2
public class Teacher extends Person {
private String teacherID;
private String department;
public Teacher(String name, String email, String teacherID, String dept) {
super(name, email); // ← เรียก parent constructor
this.teacherID = teacherID;
this.department = dept;
}
public String getTeacherID() {
return this.teacherID;
}
}
// ใช้งาน
public class Main {
public static void main(String[] args) {
Student student = new Student("John", "[email protected]", "S001");
student.displayInfo(); // ← ใช้ method จาก Person
System.out.println("ID: " + student.getStudentID());
Teacher teacher = new Teacher("Dr. Smith", "[email protected]", "T001", "CS");
teacher.displayInfo(); // ← ใช้ method จาก Person
System.out.println("ID: " + teacher.getTeacherID());
}
}
Output:
textName: John | Email: [email protected]
ID: S001
Name: Dr. Smith | Email: [email protected]
ID: T001
คำอธิบาย:
StudentและTeacherสืบทอดจากPerson- ทั้ง 2 class สามารถใช้
displayInfo()ของPersonได้ super(name, email)เรียก parent constructor เพื่อ initializenameและemail- Code ไม่ซ้ำซ้อน! ✓
What Gets Inherited?
สิ่งที่สืบทอดได้
text✓ สืบทอดได้:
├─ public methods
├─ public attributes (ไม่ดี practice)
├─ protected methods
└─ protected attributes
❌ สืบทอดไม่ได้:
├─ private methods
├─ private attributes
├─ Constructor (แต่ต้องเรียก super)
└─ static methods (เข้าถึงได้แต่ไม่ override)
ตัวอย่างที่ 2: Inheritance ด้วย Protected
มาเขียน code ที่ใช้ protected เพื่อให้ child class เข้าถึงได้
javapublic class Animal {
protected String name; // ← protected (accessible in child)
private String color; // ← private (not accessible)
public Animal(String name, String color) {
this.name = name; // ✓ Can access own private
this.color = color;
}
protected void makeSound() { // ← protected
System.out.println("Some sound");
}
public void display() {
System.out.println("Name: " + name);
System.out.println("Color: " + color);
}
}
public class Dog extends Animal {
private String breed;
public Dog(String name, String color, String breed) {
super(name, color);
this.breed = breed;
}
@Override
protected void makeSound() {
System.out.println("Woof! Woof!");
}
public void dogsInfo() {
// ✓ Can access protected name from parent
System.out.println("Dog: " + name);
// ❌ Cannot access private color from parent
// System.out.println("Color: " + color); // ERROR!
System.out.println("Breed: " + breed);
}
}
// ใช้งาน
public class Main {
public static void main(String[] args) {
Dog dog = new Dog("Buddy", "Brown", "Golden Retriever");
dog.display(); // From Animal class
dog.dogsInfo(); // From Dog class
dog.makeSound(); // Overridden method
}
}
Output:
textName: Buddy
Color: Brown
Dog: Buddy
Breed: Golden Retriever
Woof! Woof!
คำอธิบาย:
protectedmembers สามารถเข้าถึงได้จาก child classprivatemembers ไม่สามารถเข้าถึงได้จาก child classmakeSound()ถูก override (เปลี่ยนพฤติกรรม) ใน Dog class
Constructor Chaining ใน Inheritance
ทำไมต้อง super()?
เมื่อ child object ถูกสร้าง parent constructor ต้องถูกเรียก เพื่อ initialize parent’s fields
javapublic class Vehicle {
private String brand;
private int year;
public Vehicle(String brand, int year) {
this.brand = brand;
this.year = year;
System.out.println("Vehicle constructor called");
}
}
public class Car extends Vehicle {
private String color;
public Car(String brand, int year, String color) {
super(brand, year); // ← ต้องเรียก parent constructor
this.color = color;
System.out.println("Car constructor called");
}
}
// ใช้งาน
public class Main {
public static void main(String[] args) {
Car car = new Car("Toyota", 2024, "Red");
}
}
Output:
textVehicle constructor called
Car constructor called
คำอธิบาย:
super(brand, year)เรียก parent constructor ก่อน- จากนั้น child constructor ทำงาน
- ลำดับ: Parent initialization → Child initialization
ตัวอย่างที่ 3: Multi-level Inheritance
Inheritance สามารถ “ต่อเนื่อง” ได้หลายระดับ
java// Level 1: Grandparent
public class Animal {
protected String name;
public Animal(String name) {
this.name = name;
}
public void eat() {
System.out.println(name + " is eating");
}
}
// Level 2: Parent
public class Mammal extends Animal {
protected String furColor;
public Mammal(String name, String furColor) {
super(name);
this.furColor = furColor;
}
public void sleep() {
System.out.println(name + " is sleeping");
}
}
// Level 3: Child
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 class Main {
public static void main(String[] args) {
Dog dog = new Dog("Rex", "Black", "Husky");
// สามารถใช้ method จาก ทั้ง Animal, Mammal, Dog
dog.eat(); // From Animal
dog.sleep(); // From Mammal
dog.bark(); // From Dog
}
}
Output:
textRex is eating
Rex is sleeping
Rex says: Woof!
คำอธิบาย:
- Dog → Mammal → Animal (hierarchy)
- Dog สามารถใช้ method ทั้ง 3 levels ได้
- Constructor chain: Dog → Mammal → Animal
ตัวอย่างที่ 4: Inheritance ด้วย Business Logic
เขียน code ที่สมจริง
java// Parent Class
public class Employee {
private String employeeID;
private String name;
private double salary;
public Employee(String id, String name, double salary) {
this.employeeID = id;
this.name = name;
this.salary = salary;
}
public String getName() {
return this.name;
}
public double getSalary() {
return this.salary;
}
public void displayInfo() {
System.out.printf("ID: %s | Name: %s | Salary: %.2f\n",
employeeID, name, salary);
}
public double calculateBonus() {
return salary * 0.05; // 5% bonus
}
}
// Child Class 1: Manager
public class Manager extends Employee {
private int teamSize;
public Manager(String id, String name, double salary, int teamSize) {
super(id, name, salary);
this.teamSize = teamSize;
}
@Override
public double calculateBonus() {
return getSalary() * 0.10; // 10% bonus
}
public void displayInfo() {
super.displayInfo();
System.out.println("Team Size: " + teamSize);
}
}
// Child Class 2: Developer
public class Developer extends Employee {
private String programmingLanguage;
public Developer(String id, String name, double salary, String language) {
super(id, name, salary);
this.programmingLanguage = language;
}
@Override
public double calculateBonus() {
return getSalary() * 0.08; // 8% bonus
}
public void displayInfo() {
super.displayInfo();
System.out.println("Language: " + programmingLanguage);
}
}
// ใช้งาน
public class Main {
public static void main(String[] args) {
Employee emp = new Employee("E001", "John", 50000);
Manager mgr = new Manager("M001", "Alice", 80000, 5);
Developer dev = new Developer("D001", "Bob", 60000, "Java");
System.out.println("=== Employee ===");
emp.displayInfo();
System.out.println("Bonus: " + emp.calculateBonus() + "\n");
System.out.println("=== Manager ===");
mgr.displayInfo();
System.out.println("Bonus: " + mgr.calculateBonus() + "\n");
System.out.println("=== Developer ===");
dev.displayInfo();
System.out.println("Bonus: " + dev.calculateBonus());
}
}
Output:
text=== Employee ===
ID: E001 | Name: John | Salary: 50000.00
Bonus: 2500.0
=== Manager ===
ID: M001 | Name: Alice | Salary: 80000.00
Team Size: 5
Bonus: 8000.0
=== Developer ===
ID: D001 | Name: Bob | Salary: 60000.00
Language: Java
Bonus: 4800.0
คำอธิบาย:
ManagerและDeveloperสืบทอดEmployeecalculateBonus()ถูก override (เปลี่ยน logic) ใน child classes- ทุก class มี
displayInfo()แต่ Manager และ Developer แสดง info เพิ่มเติม
IS-A Relationship
Inheritance ใช้เมื่อมี “IS-A” ความสัมพันธ์
text✓ ถูกต้อง (IS-A):
├─ Dog IS-A Animal
├─ Student IS-A Person
└─ Manager IS-A Employee
❌ ผิด (HAS-A):
├─ Car HAS-A Engine (ไม่ควรใช้ inheritance)
├─ Person HAS-A Phone
└─ Employee HAS-A Office
ตัวอย่างที่ 5: IS-A vs HAS-A
java// ✓ IS-A: ใช้ Inheritance
public class SportsCar extends Car {
private int maxSpeed;
public SportsCar(String brand, int year, String color, int maxSpeed) {
super(brand, year, color);
this.maxSpeed = maxSpeed;
}
}
// ✓ HAS-A: ใช้ Composition (ไม่ใช่ inheritance)
public class Car {
private Engine engine; // ← Car HAS-A Engine
public Car(Engine engine) {
this.engine = engine;
}
}
public class Engine {
private String type;
public Engine(String type) {
this.type = type;
}
}
// ใช้งาน
public class Main {
public static void main(String[] args) {
// SportsCar IS-A Car
SportsCar ferrari = new SportsCar("Ferrari", 2024, "Red", 340);
// Car HAS-A Engine
Engine engine = new Engine("V8");
Car car = new Car(engine);
}
}
Benefits ของ Inheritance
Inheritance ให้ประโยชน์หลักๆ ดังนี้:
1. Code Reusability (ใช้ code ซ้ำ)
- ไม่ต้องเขียน code เดียวกันหลายครั้ง
- Parent methods ใช้ได้ใน child classes
2. Logical Hierarchy (ลำดับชั้นตรรกะ)
- ช่วยจัดระบบ code ให้ชัดเจน
- สะท้อนความสัมพันธ์ของ objects
3. Maintainability (ง่ายต่อการดูแล)
- แก้ bug ใน parent → child ทั้งหมด fix
- Reduce duplication
4. Extensibility (ขยายความสามารถ)
- เพิ่ม functionality ใน child ได้อย่างง่าย
- Parent ยังใช้ได้ตามปกติ
Best Practices: Inheritance
1. ใช้ Inheritance สำหรับ IS-A เท่านั้น
java// ✓ ถูกต้อง
public class Circle extends Shape {
// Circle IS-A Shape
}
// ❌ ผิด
public class Car extends Garage {
// Car doesn't IS-A Garage (should HAS-A)
}
2. ไม่ควร Extend มากเกินไป
java// ⚠️ Too deep hierarchy
A → B → C → D → E → F
// ✓ ดีกว่า
A → B
A → C
3. ใช้ super() เพื่อเรียก Parent Constructor
java// ✓ ดี
public class Student extends Person {
public Student(String name) {
super(name); // Call parent constructor
}
}
// ❌ ไม่ดี
public class Student extends Person {
public Student(String name) {
// Forgot to call super()
}
}
4. Protected > Public สำหรับ Internal Data
java// ✓ ดี
public class Parent {
protected String data; // Only child can access
}
// ❌ ไม่ดี
public class Parent {
public String data; // Anyone can access/modify
}
สรุป
การสืบทอดคุณสมบัติ (Inheritance) เป็นหนึ่งในแนวคิดหลักของ Object-Oriented Programming ที่ช่วยให้เราเขียน code ที่ ไม่ซ้ำซ้อน และ ติดตามได้ง่าย
ผ่านการใช้ inheritance เราสามารถสร้าง hierarchy ของ classes ที่แสดงความสัมพันธ์ IS-A ระหว่าง objects ได้ชัดเจน เช่น “Dog IS-A Animal” หรือ “Manager IS-A Employee” ด้วยวิธีนี้ child class สามารถ สืบทอด (inherit) methods และ attributes จาก parent class ได้ และสามารถ เพิ่มเติม หรือ ปรับแต่ง functionality ของตัวเอง
สิ่งสำคัญที่ต้องจำคือ inheritance ควรใช้เฉพาะเมื่อมี ความสัมพันธ์ IS-A ที่แท้จริง เท่านั้น และต้องระวังมิให้ hierarchy ลึกเกินไป ซึ่งจะทำให้ code ซับซ้อน เมื่อเข้าใจหลักการพื้นฐานแล้ว คุณจะพบว่า inheritance เป็นเครื่องมือที่ทรงพลัง ในการออกแบบโปรแกรมที่มีประสิทธิภาพและยืดหยุ่น
