Khác nhau giữa "self" và "static" trong PHP
PHP 5.3 giới thiệu tính năng có tên là late static binding trong đó sự tương tự giữa cách sử dụng của hai từ khoá self
và static
có thể khiến nhiều bạn cảm thấy bối rối. Để phân biệt được sự khác biệt này chúng ta hãy cùng nhau tham khảo một ví dụ sau:
<?php
class Monkey
{
protected static $legs = 4;
public static function countLegs() {
return self::$legs;
}
}
class Human extends Monkey
{
protected static $legs = 2;
}
Ở trên chúng ta có hai class Monkey
(động vật) và Human
(con người) trong đó class Human
thừa kế lại class Monkey
. Trong class Monkey
chúng ta có thuộc tính $legs
được khai báo là thuộc tính static
. Điều này là hợp lý vì chúng ta muốn số lượng chân của Monkey
không thay đổi cho tất cả các object sinh ra từ class này. Trong lớp Human
thuộc tính này được override lại về giá trị là 2.
Bây giờ chúng ta sẽ thử gọi phương thức countLegs()
có trong lớp Human
bằng việc thêm đoạn code dưới đây vào phía cuối:
echo Human::countLegs() . "\n";
Lúc này nếu chạy đoạn code trên thì giá trị trả về là 4
trong khi giá trị chúng ta cần là 2
. Điều này xảy ra là bởi vì khi sử dụng self
thì giá trị thuộc tính sẽ được tham chiếu về giá trị của thuộc tính trong lớp cha thay vì lớp hiện tại.
Để khắc phục tình trạng trên PHP phiên bản 5.3 cung cấp tính năng late static binding.
Late Static Binding trong PHP
Để hiểu late static binding là gì thì thì bạn thay đổi đoạn code khai báo lớp Monkey
ở trên thành như sau:
<?php
class Monkey
{
protected static $legs = 4;
public static function countLegs() {
return static::$legs;
}
}
Ở đoạn code cập nhật phía trên chúng ta chỉ thay đổi khoá self
bằng từ khoá static
trong phương thức countLegs()
, còn lại các phần khác vẫn được giữ nguyên.
Bây giờ nếu chạy đoạn code được cập nhật bạn sẽ có kết quả trả về là 4
thay vì là 2
như trước đây. Đây chính là cái gọi là late static binding trong PHP. Khi sử dụng từ khoá static
thay vì self
thì giá trị của thuộc tính trong phương thức countLegs()
sẽ tham chiếu tới giá trị trong lớp hiện tại đang sử dụng để gọi phương thức này (ở ví dụ trên là giá trị thuộc tính $legs
trong lớp Human
thay vì Monkey
.
Bài Tập Nhỏ Phân Biệt self
và static
Ở trên chúng ta đã tìm hiểu về late static binding. Để chắc chắn bạn đã hiểu về khái niệm này thì bây giờ bạn hãy tham khảo đoạn code phía dưới và đoán xem giá trị trả về là gì?
<?php
class A {
public static function returnClassName() {
return __CLASS__;
}
public static function printClassName() {
self::returnClassName();
}
}
class B extends A {
public static function returnClassName() {
return __CLASS__;
}
}
B::printClassName();
Để lại comment phía dưới nếu bạn đã có câu trả lời : )
Trong class A method printClassName thiếu return nên nó return NULL.