ข้ามไปยังเนื้อหาหลัก
คู่มือระบบ เนื้อหาผ่านการตรวจสอบแล้ว

Implementing Interfaces: การปฏิบัติตามสัญญา

บทความนี้อธิบายถึงการ "Implement" Interface ใน PHP ซึ่งหมายถึงการที่ Class หนึ่งประกาศว่าจะปฏิบัติตามสัญญาที่ Interface กำหนด โดยจะต้องมี Method ที่มี Signature...

Implementing Interfaces: การปฏิบัติตามสัญญา

จากบทที่แล้ว เราได้เรียนรู้เกี่ยวกับ Interface ซึ่งเปรียบเสมือน "สัญญา" ที่กำหนดว่า Class ใดๆ ที่ต้องการ "เซ็นสัญญา" นี้ จะต้องมี Method อะไรบ้าง ในบทนี้ เราจะมาดูวิธีการ "Implement" Interface หรือการปฏิบัติตามสัญญานั้นจริงๆ ว่าต้องทำอย่างไร และมีประโยชน์อย่างไร

ความหมายของการ Implement

คำว่า "Implement" ในบริบทของ Interfaces หมายถึง การที่ Class หนึ่ง ประกาศว่าตัวเองจะปฏิบัติตาม "สัญญา" ที่ Interface ได้กำหนดไว้ นั่นคือ Class นั้นจะต้องมี Method ทุก Method ที่ Interface ได้ระบุไว้ โดย Method เหล่านั้นจะต้องมีชื่อ, ประเภทของ Argument (ถ้ามี) และประเภทของค่าที่ส่งกลับ (Return Type) ตรงตามที่ Interface กำหนด

การ Implement Interfaces

ใน PHP เราใช้ Keyword implements เพื่อบอกว่า Class หนึ่ง จะ Implement Interface ใด ตัวอย่างเช่น:

interface Logger {
    public function log(string $message): void;
}

class FileLogger implements Logger {
    public function log(string $message): void {
        // เขียน Log ลงไฟล์
        $file = fopen('log.txt', 'a');
        fwrite($file, date('Y-m-d H:i:s') . ': ' . $message . "\n");
        fclose($file);
    }
}

class DatabaseLogger implements Logger {
    public function log(string $message): void {
        // บันทึก Log ลง Database
        // (โค้ดสำหรับบันทึกลง Database จะอยู่ในส่วนนี้)
        echo "บันทึก Log ลง Database: " . $message . "\n";
    }
}

$fileLogger = new FileLogger();
$fileLogger->log("ข้อความ Log จาก FileLogger");

$databaseLogger = new DatabaseLogger();
$databaseLogger->log("ข้อความ Log จาก DatabaseLogger");

ในตัวอย่างนี้:

  • เราได้สร้าง Interface ชื่อ Logger ซึ่งมี Method เดียว คือ log() ที่รับ String เป็น Argument และไม่มีค่าที่ส่งกลับ (void)
  • Class FileLogger และ DatabaseLogger ต่างก็ implements Logger นั่นหมายความว่า Class ทั้งสองนี้ จะต้องมี Method log() ที่มี Signature (ชื่อ, Argument, Return Type) ตรงกับที่ Interface Logger กำหนด
  • ใน FileLogger เรา Implement Method log() โดยการเขียน Log ลงไฟล์
  • ใน DatabaseLogger เรา Implement Method log() โดยการบันทึก Log ลง Database (ในตัวอย่างนี้ เราแค่ echo ข้อความออกมา)

ข้อควรระวัง: ถ้า Class ใด implements Interface แล้ว แต่ไม่ได้ Implement Method ทุก Method ที่ Interface กำหนด PHP จะแสดง Error ทันที

interface Speaker {
    public function speak(): string;
    public function announce(string $message): void;
}

class Dog implements Speaker {
    public function speak(): string {
        return "Woof!";
    }

    // ลืม Implement announce() method
}

// บรรทัดด้านล่างนี้ จะทำให้เกิด Error เพราะ Dog ไม่ได้ Implement announce()
// $dog = new Dog();

ในตัวอย่างนี้ Class Dog Implement Speaker แต่ Implement แค่ speak() Method เท่านั้น ทำให้เกิด Error เมื่อพยายามสร้าง Object จาก Class Dog PHP จะแจ้งว่า Class Dog ต้อง Implement Method announce ด้วย

การ Implement หลาย Interfaces

Class หนึ่ง สามารถ Implement หลาย Interfaces ได้ โดยคั่นด้วยเครื่องหมาย Comma (,) ตัวอย่างเช่น:

interface Eatable {
    public function eat(): void;
}

interface Sleepable {
    public function sleep(): void;
}

class Cat implements Eatable, Sleepable {
    public function eat(): void {
        echo "แมวกินอาหาร\n";
    }

    public function sleep(): void {
        echo "แมวกำลังนอน\n";
    }
}

$cat = new Cat();
$cat->eat();
$cat->sleep();

ในตัวอย่างนี้ Class Cat Implement ทั้ง Interface Eatable และ Sleepable ดังนั้น Cat จะต้องมี Method eat() และ sleep()

ข้อดีของการใช้ Interfaces

การใช้ Interfaces มีข้อดีหลายประการ ดังนี้:

  • Loose Coupling: Interfaces ช่วยลดการพึ่งพากัน (Coupling) ระหว่าง Class ต่างๆ Class ที่ใช้ Interface จะไม่สนใจว่า Class ที่ Implement Interface นั้น ทำงานอย่างไร เพียงแต่รู้ว่า Class นั้น มี Method ที่ Interface กำหนดไว้ ทำให้ Code มีความยืดหยุ่นและแก้ไขได้ง่าย
  • Polymorphism: Interfaces เป็นพื้นฐานสำคัญของ Polymorphism (ความสามารถในการปรับเปลี่ยนรูปแบบ) เราสามารถใช้ Interface เป็น Type ของ Variable หรือ Argument ใน Method ได้ ซึ่งจะทำให้เราสามารถส่ง Object ของ Class ใดก็ได้ ที่ Implement Interface นั้น เข้ามาได้
  • Code Reusability: Interfaces ช่วยให้เราสามารถเขียน Code ที่ทำงานกับ Object ที่ Implement Interface ได้ โดยไม่ต้องสนใจว่า Object นั้น เป็น Instance ของ Class อะไร ทำให้ Code ของเราสามารถนำกลับมาใช้ใหม่ได้ง่ายขึ้น
  • Testability: Interfaces ช่วยให้เราสามารถเขียน Unit Test ได้ง่ายขึ้น เราสามารถสร้าง Mock Object ที่ Implement Interface เพื่อจำลองการทำงานของ Class จริง และทดสอบ Code ของเราได้อย่างอิสระ

ตัวอย่างการใช้งานจริง:

ลองจินตนาการว่าเรากำลังสร้างระบบแจ้งเตือน (Notification System) เราอาจจะมีหลายช่องทางในการแจ้งเตือน เช่น Email, SMS, Push Notification

interface Notifier {
    public function sendNotification(string $message, string $recipient): bool;
}

class EmailNotifier implements Notifier {
    public function sendNotification(string $message, string $recipient): bool {
        // โค้ดสำหรับส่ง Email
        echo "ส่ง Email ไปที่ " . $recipient . " ข้อความ: " . $message . "\n";
        return true; // สมมติว่าส่งสำเร็จ
    }
}

class SMSNotifier implements Notifier {
    public function sendNotification(string $message, string $recipient): bool {
        // โค้ดสำหรับส่ง SMS
        echo "ส่ง SMS ไปที่ " . $recipient . " ข้อความ: " . $message . "\n";
        return true; // สมมติว่าส่งสำเร็จ
    }
}

class NotificationService {
    private $notifier;

    public function __construct(Notifier $notifier) {
        $this->notifier = $notifier;
    }

    public function send(string $message, string $recipient): void {
        $this->notifier->sendNotification($message, $recipient);
    }
}

// การใช้งาน
$emailNotifier = new EmailNotifier();
$smsNotifier = new SMSNotifier();

$notificationService1 = new NotificationService($emailNotifier);
$notificationService1->send("สวัสดีจากระบบ", "user@example.com");

$notificationService2 = new NotificationService($smsNotifier);
$notificationService2->send("สวัสดีจากระบบ", "0812345678");

ในตัวอย่างนี้:

  • เราสร้าง Interface Notifier เพื่อกำหนดว่า Class ที่ใช้ส่ง Notification ต้องมี Method sendNotification()
  • EmailNotifier และ SMSNotifier Implement Notifier และ Implement Method sendNotification() โดยการส่ง Email และ SMS ตามลำดับ
  • NotificationService รับ Notifier เป็น Constructor Argument (Dependency Injection)
  • เมื่อเราต้องการส่ง Notification เราสามารถสร้าง Instance ของ NotificationService โดยส่ง Instance ของ EmailNotifier หรือ SMSNotifier ก็ได้

ข้อดีคือ NotificationService ไม่ได้ผูกติดกับ EmailNotifier หรือ SMSNotifier โดยตรง แต่ผูกติดกับ Interface Notifier แทน ทำให้เราสามารถเพิ่มช่องทางการแจ้งเตือนใหม่ๆ ได้ง่าย โดยไม่ต้องแก้ไข NotificationService เพียงแค่สร้าง Class ใหม่ ที่ Implement Notifier และส่ง Instance ของ Class นั้น ให้กับ NotificationService

สรุปแล้ว การ Implement Interfaces เป็นหัวใจสำคัญของการเขียนโปรแกรมเชิงวัตถุที่ยืดหยุ่นและบำรุงรักษาง่าย ช่วยให้เราสามารถสร้าง Code ที่สามารถปรับเปลี่ยนและขยายได้ง่ายขึ้น โดยไม่ต้องแก้ไข Code เดิมมากนัก ในบทต่อไป เราจะมาเรียนรู้เกี่ยวกับ Polymorphism ซึ่งเป็นผลพลอยได้ที่สำคัญจากการใช้ Interfaces

Office.in.th Custom Service

ต้องการพัฒนาระบบหรือปรับแต่งจากโครงสร้างนี้?

Office.in.th รับพัฒนาและออกแบบ Enterprise Web Application, API Integration และระบบบริหารงานภาครัฐ/เอกชน พร้อมการสนับสนุนระยะยาว

ดูบริการรับพัฒนาซอฟต์แวร์