การนำอินเทอร์เฟซไปใช้ในการเขียนโปรแกรมเชิงวัตถุใน PHP

สรุปแล้ว เราได้ทราบมาแล้วว่าอินเทอร์เฟซเป็นวิธีที่ดี ในการควบคุมให้มั่นใจว่าเมธอดที่จำเป็นทั้งหมดของคลาส ได้รับการนำไปใช้งาน

เรามาดูอีกตัวอย่างหนึ่งที่ใช้ได้จริงมากขึ้น สมมติว่าเรามีคลาสที่ใช้เก็บอาร์เรย์ของอ็อบเจกต์รูปทรง:

FiguresCollection.php<?php
  class FiguresCollection
  {
    private $figures = []; // อาร์เรย์สำหรับรูปทรง
  }
?>

มาimplementเมธอด addFigure ในคลาสของเราเพื่อเพิ่มอ็อบเจกต์ลงในคอลเลกชัน:

FiguresCollection.php<?php
  class FiguresCollection
  {
    private $figures = [];
    
    // ส่งผ่านอ็อบเจกต์ของรูปทรงเป็นพารามิเตอร์:
    public function addFigure($figure)
    {
      $this->figures[] = $figure;
    }
  }
?>

เห็นได้ชัดว่าเราคาดหวังว่าพารามิเตอร์ของเมธอด addFigure จะ เป็นอ็อบเจกต์ของรูปทรงที่ถูกส่งผ่านเข้ามา แต่ว่า ไม่มีอะไรควบคุมเรื่องนี้เลย!

มาใช้type hintและ ระบุประเภทของอ็อบเจกต์อย่างชัดเจนว่าเป็น Figure:

FiguresCollection.php<?php
  class FiguresCollection
  {
    private $figures = [];
    
    public function addFigure(Figure $figure)
    {
      $this->figures[] = $figure;
    }
  }
?>

มาทำความเข้าใจกับสิ่งที่เราได้ทำไป

ถ้า Figure เป็นคลาสที่มีอยู่จริง เราก็จะสามารถส่งอ็อบเจกต์ของคลาสนี้และ คลาสลูกของมันเข้าไปในพารามิเตอร์ของเมธอดได้

แต่สำหรับเรา Figure นั้นคืออินเทอร์เฟซ ในกรณีนี้ type hint หมายความว่า พารามิเตอร์ของเมธอดจะรับได้เฉพาะ อ็อบเจกต์ของคลาสที่implementอินเทอร์เฟซของเรา

มาลองสร้างอ็อบเจกต์ของคลาสเรา และเพิ่มรูปทรงเข้าไป:

index.php<?php
  $figuresCollection = new FiguresCollection;
  
  // เพิ่มสี่เหลี่ยมจัตุรัสสองสามอัน:
  $figuresCollection->add(new Quadrate(2));
  $figuresCollection->add(new Quadrate(3));
  
  // เพิ่มสี่เหลี่ยมผืนผ้าสองสามอัน:
  $figuresCollection->add(new Rectangle(2, 3));
  $figuresCollection->add(new Rectangle(3, 4));
?>

การพยายามเพิ่มอ็อบเจกต์ของคลาสอื่นใด จะทำให้เกิดข้อผิดพลาด:

index.php<?php
  $figuresCollection = new FiguresCollection;
  
  class Test {}; // คลาสอื่น
  $figuresCollection->add(new Test); // จะเกิดข้อผิดพลาด
?>

การควบคุมแบบนี้ให้อะไรกับเราจริงๆ: เนื่องจากรูปทรงทั้งหมดที่ถูกเพิ่มลงในคอลเลกชัน ต่างimplementอินเทอร์เฟซ Figure เราสามารถ มั่นใจได้ว่าแต่ละอันจะมีเมธอด getSquare และเมธอด getPerimeter

ในอนาคตอาจจะมีสามเหลี่ยมเพิ่มขึ้นมา นอกเหนือจากสี่เหลี่ยมจัตุรัสและสี่เหลี่ยมผืนผ้า ในกรณีนี้ สามเหลี่ยมก็จะมี เมธอด getSquare และ getPerimeter เช่นกัน

ในทางปฏิบัติสิ่งนี้ทำให้เกิดสิ่งต่อไปนี้: เราสามารถ ในคลาส FiguresCollection สร้าง เช่น เมธอด getTotalSquare เพื่อหา พื้นที่ทั้งหมดของรูปทรงในคอลเลกชัน ในเมธอดนี้ เราจะวนลูปผ่านอาร์เรย์ของรูปทรงและ เรียกใช้ เมธอด getSquare ในแต่ละรูปทรง

เนื่องจากแต่ละรูปทรงimplementอินเทอร์เฟซ Figure เราจึงมั่นใจได้ถึง 100% ว่าแต่ละรูปทรงจะมี เมธอด getSquare นี้

สรุป นี่คือการimplementเมธอด:

php<?php
  class FiguresCollection
  {
    private $figures = [];
    
    public function addFigure(Figure $figure)
    {
      $this->figures[] = $figure;
    }
    
    // หาพื้นที่รวม:
    public function getTotalSquare()
    {
      $sum = 0;
      
      foreach ($this->figures as $figure) {
        $sum += $figure->getSquare(); // ใช้เมธอด getSquare
      }
      
      return $sum;
    }
  }
?>
Задание 1

โดยไม่แอบดูโค้ดของฉัน ลองimplement คลาส FiguresCollection แบบเดียวกันดู

Задание 2

เพิ่มเมธอด getTotalPerimeter ลงในคลาส FiguresCollection เพื่อหา ความยาวรอบรูปรวมของรูปทรงทั้งหมด