[OOP]: Giới thiệu về sự kế thừa và tầm vực của phương thức và thuộc tính
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
<?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:
From a new method in MyOtherClass.
I’m a class property!
The class “MyClass” was destroyed.
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
<?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(); ?> |
Kết quả dữ liệu xuất ra trên trình sẽ thay đổi như sau:
From a new method in MyOtherClass.
I’m a class property!
The class “MyClass” was destroyed.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
<?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(); ?> |
Kết quả sẽ xuất ra giá trị của cả phương thức constructor của class cha lẫn giá trị phương thức constructor của class con:
A new constructor in MyOtherClass.
From a new method in MyOtherClass.
I’m a class property!
The class “MyClass” was destroyed.
Để gia tăng khả năng kiểm soát các object, các phương thức và thuộc tính sẽ được gán thêm những giá trị tầm vực. Nó cho phép chúng ta kiểm soát khả năng truy cập (như thế nào và ở nơi đâu) của thuộc tính và phương thức. Chúng ta có ba từ khóa để đảm nhiệm việc này:public,protected, vàprivate. Ngoài ra, còn có một từ khóa nữa cũng có khả năng đảm nhiệm việc này, đó là static, nó cho phép các thuộc tính và phương thức có thể được truy cập mà không cần khởi tạo class.
Chú ý: tầm vực của thuộc tính và phương thức là 2 tính năng mới của PHP 5.
Thuộc Tính và Phương Thức Mang Tầm Vực Public
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
<?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(); ?> |
Chạy script, và bạn sẽ nhận được thông báo lỗi như sau:
A new constructor in MyOtherClass.
Fatal error: Call to protected method MyClass::getProperty() from context ” in /Applications/XAMPP/xamppfiles/htdocs/testing/test.php on line 55
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
<?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(); ?> |
Và kết quả sẽ đúng như bạn mong muốn:
A new constructor in MyOtherClass.
I’m a class property!
The class “MyClass” was destroyed.
Một thuộc tính hay phương thức được gán private thì chỉ có thể truy cập được bên trong class đã định nghĩa nó. Điều này có nghĩa là ngay cả khi có 1 class kế thừa class đã định nghĩa một thuộc tính private, thuộc tính hay phương thức này cũng sẽ không tồn tại trong toàn bộ class con.
Để chứng minh điều này, chúng ta sẽ khai báo phương thức getProperty() là private trong MyClass, và cố gắng truy cập nó thông qua một phương thức public callProtected()từ MyOtherClass(class kế thừa MyClass):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
<?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.
Fatal error: Call to private method MyClass::getProperty() from context ‘MyOtherClass’ in /Applications/XAMPP/xamppfiles/htdocs/testing/test.php on line 49
Thuộc Tính và Phương Thức Static
Một phương thức hay thuộc tính được gán tầm vực static có thể truy cập được ngay cả khi bạn không khởi tạo class, bạn chỉ cần cung cấp tên class, toán tử phân giải phạm vi (::), và tên thuộc tính hoặc phương thức.
“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.”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
<?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 ); ?> |
Chú ý: Khi truy cập các thuộc tính static,ký tự độ la ($) sẽ nằm sau toán tử phân giải phạm vi (::).
Khi bạn load script này trên trình duyệt, nó sẽ xuất ra kết quả như sau:
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.
(Vũ Anh Tuấn)
Leave a Reply