จากโพสที่แล้ว 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 ได้เลย ซึ่งความสามารถในการจะทำเช่นนี้ได้เป็นสิ่งที่มีประโยชน์มากในการออกแบบโปรแกรมแบบต่างๆต่อไป