บทนำ: ทำไมต้องมี Abstract Class และ Interface ในภาษา Java?
เมื่อคุณเริ่มสร้างโปรแกรมขนาดใหญ่ จะพบว่า classes หลายชนิดมีพฤติกรรมร่วมที่ควบคุมไม่ได้ด้วย inheritance แบบเดียว (ต่อสายจาก superclass เส้นเดียว) และบางครั้งต้องการ “สัญญา (contract)” ว่า ถ้าใครจะ implement ระบบนี้ได้ ต้องมี method อะไรบ้าง
Java จึงมีเครื่องมือให้ 2 แบบสำหรับ “ออกแบบพฤติกรรมร่วม” คือ
- Abstract Class
- Interface
สองอย่างนี้มีอยู่เพื่อช่วยแก้ปัญหาการ reuse code (ใช้ซ้ำ), กำหนดข้อบังคับในระบบ และ ออกแบบให้งานแต่ละส่วนเปลี่ยนแทนกันได้ แม้โค้ดจะเป็นของ “คนละตระกูล” ก็ตาม
- บทนำ: ทำไมต้องมี Abstract Class และ Interface ในภาษา Java?
- Abstract Class คืออะไร?
- ตัวอย่าง: สืบทอดและ implement abstract method
- Interface คืออะไร?
- ตัวอย่าง: Implement interface หลายตัว
- เปรียบเทียบ Abstract Class vs Interface
- Code สำหรับเทียบ
- ตารางเปรียบเทียบ
- ตัวอย่างที่ 3: ใช้ร่วมกัน
- หลักคิดในการเลือกใช้
- เมื่อไรควรใช้ Abstract Class?
- เมื่อไรควรใช้ Interface?
- สรุป
Abstract Class คืออะไร?
Abstract Class คือ class ที่ ไม่สามารถสร้าง object ได้ตรงๆ แต่ใช้เป็น “แม่แบบ” ให้ลูก (subclass) สืบทอด
javapublic abstract class Animal {
protected String name;
public Animal(String name) {
this.name = name;
}
// abstract method: ไม่มี code ต้องให้ subclass ทำเอง
public abstract void makeSound();
public void sleep() {
System.out.println(name + " is sleeping");
}
}
คำอธิบาย:
- ใส่
abstractหน้าชื่อ class → สร้าง object จาก class นี้ตรงๆ ไม่ได้ abstract methodคือ method ที่ไม่มี code (body) ต้องให้ subclass เขียนเอง- สามารถมี method ปกติ (มี code) ร่วมด้วยได้
ตัวอย่าง: สืบทอดและ implement abstract method
javapublic class Dog extends Animal {
public Dog(String name) {
super(name);
}
@Override
public void makeSound() {
System.out.println(name + " says: Woof!");
}
}
public class Cat extends Animal {
public Cat(String name) {
super(name);
}
@Override
public void makeSound() {
System.out.println(name + " says: Meow!");
}
}
// การใช้งาน
public class Main {
public static void main(String[] args) {
Animal dog = new Dog("Rex");
dog.makeSound(); // Rex says: Woof!
dog.sleep(); // Rex is sleeping
Animal cat = new Cat("Kitty");
cat.makeSound(); // Kitty says: Meow!
cat.sleep(); // Kitty is sleeping
// Animal animal = new Animal("something"); // ❌ ERROR! สร้าง object ไม่ได้
}
}
สิ่งที่เห็น:
DogและCatต้อง implementmakeSound()เองsleep()มี code อยู่ใน abstract class ใช้ซ้ำได้Animalเป็น blueprint, ไม่ใช่ object จริง
Interface คืออะไร?
Interface คือ “ชุดสัญญา (contract)” ลงไว้ว่า “ถ้า class ใด implement interface นี้ ต้องมี method เหล่านี้แน่นอน” (แต่ไม่มี code เลย)
javapublic interface Flyable {
void fly();
}
คำอธิบาย:
- ใส่
interfaceแทนclass - สามารถมีได้เฉพาะ abstract method (Java 8+: มี default/static ได้ แต่ตอนนี้โฟกัสที่ “ไม่มี code” ก่อน)
- class ที่ implement ต้องเขียน method ทั้งหมด
- object สร้างจาก interface ตรงๆ ไม่ได้
ตัวอย่าง: Implement interface หลายตัว
javapublic interface Swimmable {
void swim();
}
public interface Flyable {
void fly();
}
public class Duck implements Swimmable, Flyable {
@Override
public void swim() {
System.out.println("Duck is swimming");
}
@Override
public void fly() {
System.out.println("Duck is flying");
}
}
public class Fish implements Swimmable {
@Override
public void swim() {
System.out.println("Fish is swimming");
}
}
// การใช้งาน
public class Main {
public static void main(String[] args) {
Duck duck = new Duck();
duck.swim(); // Duck is swimming
duck.fly(); // Duck is flying
Swimmable swimmer = new Fish();
swimmer.swim(); // Fish is swimming
// Flyable flyer = new Fish(); // ❌ ERROR! Fish ไม่ได้ implement Flyable
}
}
สิ่งที่เห็น:
- Class เดียว implement interface ได้หลายตัว (Duck เป็นได้ทั้ง Swimmable และ Flyable)
- Interface ทำหน้าที่เป็น “หัวข้อบังคับ”
- ใคร implement ก็ต้องทำ method ให้ครบ
เปรียบเทียบ Abstract Class vs Interface
Code สำหรับเทียบ
java// Abstract class
public abstract class Vehicle {
public abstract void move(); // abstract method
public void fuelUp() { // concrete method
System.out.println("Fuel added!");
}
}
// Interface
public interface Electric {
void charge();
}
public class ElectricCar extends Vehicle implements Electric {
@Override
public void move() {
System.out.println("ElectricCar moves silently");
}
@Override
public void charge() {
System.out.println("Car is charging");
}
}
คำอธิบาย:
ElectricCarสืบทอด abstract class (extend) และ implement interface ได้พร้อมกัน- abstract class ใช้สืบทอดพฤติกรรมพื้นฐาน
- interface เพิ่มความสามารถแบบ plug-in
ตารางเปรียบเทียบ
| คุณสมบัติ | Abstract Class | Interface |
|---|---|---|
| สืบทอดต่อกันได้ | ได้ (extends 1 ชนิด) | ได้ (implements ได้หลายอัน) |
| มี method พร้อม code ได้ไหม | ได้ | (ตั้งแต่ Java 8) ได้บ้าง (default) |
| มีตัวแปร (field) ได้ไหม | ได้ (instance/static) | ได้แต่ static final (constant) เท่านั้น |
| instance สร้างได้ไหม | ไม่ได้ | ไม่ได้ |
| ใช้ polymorphism ได้ไหม | ได้ | ได้ |
| เหมาะกับ | ความสัมพันธ์ IS-A | ความสามารถเสริม (Can do) |
ตัวอย่างที่ 3: ใช้ร่วมกัน
javapublic interface Payable {
void pay();
}
public abstract class Employee {
protected String name;
public Employee(String name) { this.name = name; }
public abstract void work();
}
public class FullTimeEmployee extends Employee implements Payable {
public FullTimeEmployee(String name) {
super(name);
}
@Override
public void work() { System.out.println(name + " works 8 hrs."); }
@Override
public void pay() { System.out.println(name + " gets salary."); }
}
public class Contractor extends Employee implements Payable {
public Contractor(String name) {
super(name);
}
@Override
public void work() { System.out.println(name + " works flexible."); }
@Override
public void pay() { System.out.println(name + " gets wage."); }
}
public class Main {
public static void main(String[] args) {
Payable e1 = new FullTimeEmployee("Alice");
Payable e2 = new Contractor("Bob");
e1.pay(); // Alice gets salary.
e2.pay(); // Bob gets wage.
}
}
คำอธิบาย:
- สร้าง “กลุ่ม” ด้วย interface (ทุกคนที่ implement Payable จะ .pay() ได้)
- ใช้ abstract class จัดการ common fields/behavior และใช้ interface เป็นความสามารถเฉพาะ
หลักคิดในการเลือกใช้
เมื่อไรควรใช้ Abstract Class?
- ถ้ามีพฤติกรรมพื้นฐานและโครงสร้างที่แชร์กัน
- ต้องการกำหนด method บางส่วนให้ลูก class
- Code reuse บางส่วนได้เลย
เมื่อไรควรใช้ Interface?
- เมื่ออยากให้ “class ใดๆ” ก็ตาม implement ความสามารถนั้นได้ (แม้ไม่ได้อยู่ในสายพันธุ์เดียวกัน)
- เมื่ออยากให้ class implement ได้หลายความสามารถพร้อมกัน
- ใช้สร้าง contract บังคับ และ design แบบ plug-and-play
สรุป
Abstract class และ interface เป็นเครื่องมือสำคัญในภาษา Java สำหรับการออกแบบระบบให้ทั้งมี โครงสร้างร่วม และ ความยืดหยุ่นสุดขีด
abstract class เหมาะกับสิ่งมีชีวิตหรือวัตถุที่ “เกี่ยวข้องกันจริงๆ” ในแง่สายพันธุ์ (IS-A) และมี logic สมาชิกที่แชร์ร่วมกันได้
interface เหมาะกับการสร้าง “ความสามารถเสริม” หรือ “ข้อบังคับเชิงนามธรรม” ที่หลากหลาย class (ซึ่งอาจไม่เกี่ยวดองกันเลย) จะนำไปใช้ให้ระบบทำงานแทนกันได้
การเข้าใจและเลือกใช้เครื่องมือทั้งสองอย่างนี้ จะช่วยให้คุณออกแบบโค้ดที่ชัดเจน ยืดหยุ่น ขยายง่าย และดูแลรักษาในระยะยาวได้ดีกว่าการใช้ inheritance แบบเดียวอย่างมาก
