Bài 3: Tìm hiểu sự kế thừa và tầm vực trong lập trình hướng đối tượng
Một Class có thể kế thừa các phương thức và thuộc tính của class khác, bằng cách sử dụng từ khóa extends. Ví dụ, để tạo ra một class kế thừa MyClass đồng thời thêm vào nó một phương thức, bạn sẽ có mã lệnh như sau:
<?php class MyClass { public $prop1 = "I'm a class property!"; public function __construct() { echo 'The class "', __CLASS__, '" was initiated!<br />'; } public function __destruct() { echo 'The class "', __CLASS__, '" was destroyed.<br />'; } public function __toString() { echo "Using the toString method: "; return $this->getProperty(); } public function setProperty($newval) { $this->prop1 = $newval; } public function getProperty() { return $this->prop1 . "<br />"; } } class MyOtherClass extends MyClass { public function newMethod() { echo "From a new method in " . __CLASS__ . ".<br />"; } } // Tạo đối tượng $newobj = new MyOtherClass; // Echo object ra dạng chuỗi echo $newobj->newMethod(); // Sử dụng một phương thức của class cha echo $newobj->getProperty(); ?>
Mở trình duyệt, và xem kết quả xuất ra như sau:
The class “MyClass” was initiated!
From a new method in MyOtherClass.
I’m a class property!
The class “MyClass” was destroyed.
Kỹ thuật nạp chồng trong Hướng Đối Tượng
Tại một class con, để thay đổi giá trị, tính năng của một thuộc tính hoặc phương thức đã có sẵn ở class cha, bạn chỉ cần ghi đè (nạp chồng) lên nó bằng cách khởi tạo lại chính nó trong class con:
<?php class MyClass { public $prop1 = "I'm a class property!"; public function __construct() { echo 'The class "', __CLASS__, '" was initiated!<br />'; } public function __destruct() { echo 'The class "', __CLASS__, '" was destroyed.<br />'; } public function __toString() { echo "Using the toString method: "; return $this->getProperty(); } public function setProperty($newval) { $this->prop1 = $newval; } public function getProperty() { return $this->prop1 . "<br />"; } } class MyOtherClass extends MyClass { public function __construct() { echo "A new constructor in " . __CLASS__ . ".<br />"; } public function newMethod() { echo "From a new method in " . __CLASS__ . ".<br />"; } } // Tạo object $newobj = new MyOtherClass; // Echo object ra dưới dạng chuỗi echo $newobj->newMethod(); // Sử dụng một phương thức của class cha echo $newobj->getProperty(); ?>
From a new method in MyOtherClass.
I’m a class property!
The class “MyClass” was destroyed.
<?php class MyClass { public $prop1 = "I'm a class property!"; public function __construct() { echo 'The class "', __CLASS__, '" was initiated!<br />'; } public function __destruct() { echo 'The class "', __CLASS__, '" was destroyed.<br />'; } public function __toString() { echo "Using the toString method: "; return $this->getProperty(); } public function setProperty($newval) { $this->prop1 = $newval; } public function getProperty() { return $this->prop1 . "<br />"; } } class MyOtherClass extends MyClass { public function __construct() { parent::__construct(); // Gọi hàm dựng từ class cha echo "A new constructor in " . __CLASS__ . ".<br />"; } public function newMethod() { echo "From a new method in " . __CLASS__ . ".<br />"; } } // Tạo object $newobj = new MyOtherClass; // Echo object ra dưới dạng chuỗi echo $newobj->newMethod(); // Sử dụng một phương thức của class cha echo $newobj->getProperty(); ?>
A new constructor in MyOtherClass.
From a new method in MyOtherClass.
I’m a class property!
The class “MyClass” was destroyed.
Với nhóm này, toàn bộ các phương thức và thuộc tính bạn sử dụng đều mang tính công cộng. Tức là chúng có thể được truy cập từ bất cứ nơi đâu, cà trong và ngoài class.
Khi bạn khai báo một thuộc tính hay phương thức mà không gán tầm vực cho chúng, thì PHP tự hiểu nó thuộc nhóm public.
Thuộc Tính và Phương Thức Mang Tầm Vực Protected
Khi một thuộc tính hay phương thức được khai báo tầm vựcprotected, chúng chỉ có thể truy cập được trong chính class chứa chúng, hoặc tại một class kế thừa class này.
Gán tầm vực protected cho phương thức getProperty() trong MyClass và thử truy cập nó từ bên ngoài class:
<?php class MyClass { public $prop1 = "I'm a class property!"; public function __construct() { echo 'The class "', __CLASS__, '" was initiated!<br />'; } public function __destruct() { echo 'The class "', __CLASS__, '" was destroyed.<br />'; } public function __toString() { echo "Using the toString method: "; return $this->getProperty(); } public function setProperty($newval) { $this->prop1 = $newval; } protected function getProperty() { return $this->prop1 . "<br />"; } } class MyOtherClass extends MyClass { public function __construct() { parent::__construct(); echo "A new constructor in " . __CLASS__ . ".<br />"; } public function newMethod() { echo "From a new method in " . __CLASS__ . ".<br />"; } } // Tạo object $newobj = new MyOtherClass; // Thử gọi một phương thức protected echo $newobj->getProperty(); ?>
A new constructor in MyOtherClass.
<?php class MyClass { public $prop1 = "I'm a class property!"; public function __construct() { echo 'The class "', __CLASS__, '" was initiated!<br />'; } public function __destruct() { echo 'The class "', __CLASS__, '" was destroyed.<br />'; } public function __toString() { echo "Using the toString method: "; return $this->getProperty(); } public function setProperty($newval) { $this->prop1 = $newval; } protected function getProperty() { return $this->prop1 . "<br />"; } } class MyOtherClass extends MyClass { public function __construct() { parent::__construct(); echo "A new constructor in " . __CLASS__ . ".<br />"; } public function newMethod() { echo "From a new method in " . __CLASS__ . ".<br />"; } public function callProtected() { return $this->getProperty(); } } // Tạo object $newobj = new MyOtherClass; // Gọi phương thức protected từ một phương thức public echo $newobj->callProtected(); ?>
A new constructor in MyOtherClass.
I’m a class property!
The class “MyClass” was destroyed.
<?php class MyClass { public $prop1 = "I'm a class property!"; public function __construct() { echo 'The class "', __CLASS__, '" was initiated!<br />'; } public function __destruct() { echo 'The class "', __CLASS__, '" was destroyed.<br />'; } public function __toString() { echo "Using the toString method: "; return $this->getProperty(); } public function setProperty($newval) { $this->prop1 = $newval; } private function getProperty() { return $this->prop1 . "<br />"; } } class MyOtherClass extends MyClass { public function __construct() { parent::__construct(); echo "A new constructor in " . __CLASS__ . ".<br />"; } public function newMethod() { echo "From a new method in " . __CLASS__ . ".<br />"; } public function callProtected() { return $this->getProperty(); } } // Tạo object $newobj = new MyOtherClass; // Sử dụng một phương thức từ class con echo $newobj->callProtected(); ?> Reload lại trình duyệt để xem thông báo lỗi như sau xuất hiện:
A new constructor in MyOtherClass.
“Một trong những lợi ích chính khi sử dụng thuộc tính static là chúng giữ các giá trị được lưu trữ trong suốt khoảng thời gian script tồn tại.”
<?php class MyClass { public $prop1 = "I'm a class property!"; public static $count = 0; public function __construct() { echo 'The class "', __CLASS__, '" was initiated!<br />'; } public function __destruct() { echo 'The class "', __CLASS__, '" was destroyed.<br />'; } public function __toString() { echo "Using the toString method: "; return $this->getProperty(); } public function setProperty($newval) { $this->prop1 = $newval; } private function getProperty() { return $this->prop1 . "<br />"; } public static function plusOne() { return "The count is " . ++self::$count . ".<br />"; } } class MyOtherClass extends MyClass { public function __construct() { parent::__construct(); echo "A new constructor in " . __CLASS__ . ".<br />"; } public function newMethod() { echo "From a new method in " . __CLASS__ . ".<br />"; } public function callProtected() { return $this->getProperty(); } } do { // Gọi plusOne mà không khởi tạo MyClass echo MyClass::plusOne(); } while ( MyClass::$count < 10 ); ?>
The count is 2.
The count is 3.
The count is 4.
The count is 5.
The count is 6.
The count is 7.
The count is 8.
The count is 9.
The count is 10.