PHP OOP #2: Construct และ Encapsulate ด้วย Access Modifiers

จากโพสที่แล้ว PHP OOP #1: พื้นฐานการสร้าง Class และ Object ว่าด้วยเรื่องการเขียน PHP OOP พื้นฐาน ซึ่งอาจจะดูแล้วยังไม่เห็นประโยชน์ของ OOP ที่ชัดเจนนัก อาจจะมองได้ว่าไม่ต่างจากเขียนฟังก์ชั่นเท่าไหร่ ซึ่งในโพสนี้ก็จะมาพูดถึงคุณสมบัติและฟังก์ชั่นเฉพาะของ Object Oriented คือการใช้ฟังก์ชั่น construct และการทำ encapsulation

รันคำสั่งโดยอัตโนมัติเมื่อสร้างวัตถุจากคลาส ด้วย __construct Function

หลังจากที่เราสร้าง(instantiate) วัตถุจากคลาส บ่อยครั้งที่เราจะต้องทำการตั้งค่าบางอย่าง หรือรันบางคำสั่งเพื่อทำให้วัตถุคลาสนั้นๆ สามารถใช้งานได้อย่างถูกต้องสมบูรณ์ ซึ่งเราก็อาจจะสามารถทำได้โดยเรียกใช้ฟังก์ชั่นจากคลาสนั้นๆทุกครั้งหลังสร้างวัตถุจากคลาส เช่น $obj->some_function('Dog') แต่วิธีนี้ก็อาจจะเกิดความผิดพลาดได้เมื่อลืมเรียก อีกทั้งยังทำให้ต้องเขียนโค้ดเพิ่มหลังสร้างวัตถุ ซึ่งจริงๆแล้วมีวิธีที่ดีกว่า คือการใช้ฟังก์ชั่น __construct

ฟังก์ชั่น __construct ใน PHP Class นี้ คือฟังก์ชั่นที่เป็นชื่อเฉพาะ ที่จะถูกเรียกให้ทำงานทุกครั้งเมื่อมีการสร้างวัตถุจากคลาส โดยสามารถส่งตัวแปรเข้าไปได้เช่นเดียวกับฟังก์ชั่นทั่วไป เช่น

class Pet{ 
  public $type; 
  public $name;
 
  function __construct($set_type, $set_name){ 
    $this->type = $set_type;
    $this->name = $set_name;
  }
}

// Instantiate 
$dog = new Pet('Dog','Shiro');

จากตัวอย่างในโค้ด จะเห็นว่าในฟังก์ชั่น __construct จะมีการรับค่าตัวแปรเข้ามาสองตัว คือ set_type และ set_type เพื่อนำมาใช้ตั้งค่าตัวแปรภายในวัตถุนี้ ซึ่งเราสามารถเรียกใช้ตัวแปร หรือฟังก์ชั่นจากภายในคลาสเองด้วยการเติม $this-> นำหน้า และเมื่อเราทำการสร้างวัตถุจากคลาส ก็สามารถใส่ parameter ลงในวงเล็บหลังชื่อคลาสเมื่อทำการ new ได้เลย และค่าดังกล่าวก็จะถูกส่งไปเรียกฟังก์ชั่น __construct โดยอัตโนมัติ

Encapsulate ข้อมูลและฟังก์ชั่นในคลาส ด้วย Access Modifiers

การ Encapsulation นี้เป็นคอนเซปต์พื้นฐานของ OOP คือการจำกัดการเข้าถึงหรือเรียกใช้ข้อมูลหรือฟังก์ชั่นในคลาส อาจจะมองได้ว่าเป็นการซ่อนข้อมูลภายในคลาสไว้ไม่ให้สามารถเข้าถึงได้โดยตรงจากส่วนอื่นๆของโปรแกรม เพื่อแยกระหว่างข้อมูลภายในและภายนอกคลาสไม่ให้ปนกัน และป้องกันไม่ให้โปรแกรมจากส่วนอื่นๆเข้าถึงหรือเปลี่ยนแปลงข้อมูลภายในคลาสโดยไม่ได้รับอนุญาต หรือผิดไปจากที่ผู้ออกแบบคลาสต้องการให้เป็น

ตัวอย่างการทำ Encapsulation โดยการตั้ง Access modifiers

class Pet{ 
  private $type; 
  protected $breed;
  public $name;
}

$dog = new Pet();
$dog->type = 'Dog';         // Error
$dog->breed = 'Shih Tzu';   // Error
$dog->name = 'Shiro';       // OK

จากตัวอย่างจะเห็นว่าเมื่อประกาศตัวแปรในคลาส มีการใส่ access modifiers ได้แก่

  • Private จะทำให้ตัวแปรนี้ไม่สามารถเข้าถึงได้จากนอกคลาส
  • Protected จะทำให้ตัวแปรนี้สามารถเข้าถึงได้จากคลาสที่มีการ inherit คลาสนี้ไปเท่านั้น (คอนเซปต์ของการทำ class inheritance จะกล่าวถึงในโพสต่อๆไป)
  • Public สามารถเข้าถึงได้จากทุกที่

ดังนั้น การเรียกถึงตัวแปรแบบตรงๆ ก็จะไม่สามารถทำได้ แต่เมื่อต้องการเรียกใช้เราก็ต้องเรียกผ่าน method เพื่อตั้งค่าหรือขอข้อมูล ซึ่งก็คือคอนเซปต์ของ getter, setter ดังตัวอย่าง

class Pet{ 
  private $type; 
  public $name;

  function __construct($set_type, $set_name){ 
    $this->type = $set_type;
    $this->name = $set_name;
  }
}

$dog = new Pet();
$dog->setType( 'Dog' );    // OK
$dog->getType();           // return 'Dog'

จะเห็นว่า ภายนอกจะสามารถเข้าถึงข้อมูล type ได้โดยผ่าน get, set ฟังก์ชั่นเท่านั้น ทำให้เราสามารถควบคุมการเข้าถึงและการเปลี่ยนแปลงแก้ไขข้อมูลในคลาสได้อย่างสมบูรณ์ ซึ่งในแง่ของความปลอดภัยแล้ว การทำ encapsulation ถือว่ามีประโยชน์มากเลยทีเดียว

และหากเรานำคอนเซปต์ของการ construct และ encapsulate มารวมกัน ก็จะสามารถเขียนให้สามารถตั้งค่าข้อมูลภายในคลาสได้ครั้งแรกครั้งเดียว ไม่สามารถเปลี่ยนแปลงได้ แต่สามารถนำไปใช้ได้ เช่น

class Pet{ 
  private $type; 
  public $name;

  function __construct($set_type, $set_name){ 
    $this->type = $set_type;
    $this->name = $set_name;
  }

  function getType() {
     return $this->type;
  }
}

$dog = new Pet('Dog','Shiro');
echo $dog->getType();           // echo 'Dog'
echo $dog->name;                // echo 'Shiro'

จะเห็นว่าเราจะใส่ค่า parameter ได้แก่ type และ name ลงไปตอนสร้างวัตถุเลย ซึ่งกรณีนี้หากไม่มีฟังก์ชั่น set type แล้วจะไม่สามารถเปลี่ยนแปลง type ได้เลย ซึ่งความสามารถในการจะทำเช่นนี้ได้เป็นสิ่งที่มีประโยชน์มากในการออกแบบโปรแกรมแบบต่างๆต่อไป