PlusMagi's Blog By Pitt Phunsanit

PHP: Intersection Types

Intersection Types เป็นหนึ่งในฟีเจอร์เด่นที่ถูกเพิ่มเข้ามาตั้งแต่วันที่ PHP 8.1 ซึ่งช่วยให้เราสามารถกำหนด Type ให้กับตัวแปรหรือ Parameter โดยบังคับว่าข้อมูลนั้นจะต้องเป็นสมาชิกของ ทุกๆ Type ที่กำหนดไว้พร้อมกัน (โอเปอเรเตอร์ &)

ถ้าอธิบายให้เห็นภาพง่าย ๆ


ทำไมเราถึงต้องใช้ Intersection Types?

ในโลกของการเขียนโค้ดแบบ Object-Oriented Programming (OOP) เรามักจะแบ่งความสามารถของ Object ออกเป็น Interface ย่อยๆ ตามหลัก Interface Segregation Principle (ซอย Interface ให้เล็กลงเพื่อให้ทำงานเฉพาะทาง)

แต่ปัญหาจะเกิดตอนที่เราอยากสร้างฟังก์ชันที่ต้องการ Object ที่มีความสามารถจาก หลาย ๆ Interface พร้อมกัน ### ตัวอย่างปัญหา (ก่อน PHP 8.1) สมมติว่าเรามี 2 อินเตอร์เฟส คือ Countable (นับจำนวนได้) และ Iterator (วนลูปได้) ถ้าเราอยากสร้างฟังก์ชันที่รับค่าเข้ามาแล้วต้องทั้งนับได้และวนลูปได้ด้วย เราทำได้แค่

  1. เลือก Type ใด Type หนึ่ง แล้วไปเช็คด้วย is_a() หรือ instanceof ข้างในฟังก์ชันเอาเอง (ซึ่งโค้ดจะไม่สวยและเสี่ยงพังตอน Runtime)
  2. สร้าง Interface ใหม่ขึ้นมาผูกรวมกัน เช่น interface CountableIterator extends Countable, Iterator {} ซึ่งทำให้เกิดขยะในระบบโดยไม่จำเป็น

วิธีการใช้งานใน PHP 8.1+

ด้วย Intersection Types เราสามารถใช้เครื่องหมายแอมเพอร์แซนด์ (&) เชื่อม Type ที่เราต้องการได้ทันที โดยไม่ต้องสร้าง Interface ใหม่ขึ้นมาให้รกตระกูล

interface Serializable {
    public function serialize(): string;
}

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

// ฟังก์ชันนี้จะรับเฉพาะ Object ที่ implement ทั้ง Serializable และ Loggable เท่านั้น
function processData(Serializable & Loggable $item) {
    // สามารถเรียกใช้ Method จากทั้งสอง Interface ได้อย่างปลอดภัย
    $item->log("Processing item...");
    return $item->serialize();
}

หากเราส่ง Object ที่มีแค่ความสามารถเดียว หรือไม่ครบตามเงื่อนไข PHP จะโยน TypeError ออกมาให้ทันทีตั้งแต่ต้นทาง ช่วยลด Bug ได้มหาศาล


ข้อจำกัดสำคัญที่ควรรู้

แม้ว่าจะทรงพลัง แต่ Intersection Types มีกฎเหล็กที่ต้องจำไว้ดังนี้ครับ


สรุป

Intersection Types ช่วยให้การทำ Type Hinting ใน PHP มีความยืดหยุ่นและปลอดภัยมากขึ้น เหมาะมากสำหรับการเขียนโค้ดสไตล์ Clean Architecture หรือการออกแบบระบบที่เน้น Composition over Inheritance (การประกอบร่างมากกว่าการสืบทอดคลาส)


อ่านเพิ่มเติม

Exit mobile version