Abstract Class vs Interface

บทนำ: ทำไมต้องมี Abstract Class และ Interface ในภาษา Java?

เมื่อคุณเริ่มสร้างโปรแกรมขนาดใหญ่ จะพบว่า classes หลายชนิดมีพฤติกรรมร่วมที่ควบคุมไม่ได้ด้วย inheritance แบบเดียว (ต่อสายจาก superclass เส้นเดียว) และบางครั้งต้องการ “สัญญา (contract)” ว่า ถ้าใครจะ implement ระบบนี้ได้ ต้องมี method อะไรบ้าง

Java จึงมีเครื่องมือให้ 2 แบบสำหรับ “ออกแบบพฤติกรรมร่วม” คือ

  • Abstract Class
  • Interface

สองอย่างนี้มีอยู่เพื่อช่วยแก้ปัญหาการ reuse code (ใช้ซ้ำ), กำหนดข้อบังคับในระบบ และ ออกแบบให้งานแต่ละส่วนเปลี่ยนแทนกันได้ แม้โค้ดจะเป็นของ “คนละตระกูล” ก็ตาม


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 ต้อง implement makeSound() เอง
  • 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 ClassInterface
สืบทอดต่อกันได้ได้ (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 แบบเดียวอย่างมาก