Sự khác nhau giữa Self và Static trong PHP
Đặt vấn đề Chúng ta cùng tìm hiểu qua một số đoạn code ví dụ như dưới đây. Giả sử chúng ta có class Car như sau : class Car { public static function model ( ) { self : : getModel ( ) ; } protected static function getModel ( ) { ...
Đặt vấn đề
Chúng ta cùng tìm hiểu qua một số đoạn code ví dụ như dưới đây. Giả sử chúng ta có class Car như sau :
class Car { public static function model() { self::getModel(); } protected static function getModel() { echo "I am a Car!"; } }
Ta có thể thấy method model()của class Car là static method. Nên ta có thể sử dụng mà không cần khởi tạo đối tượng :
Car::model();
Kết quả sẽ là :
I am a Car!
Từ khóa self sẽ gọi hàm getModel thuộc về class Car và in ra dòng chữ "I am a Car" như trên. Bây giờ chúng ta sẽ tạo thêm một class gọi là class Mercedes kế thừa class Car ở trên
class Mercedes extends Car { protected static function getModel() { echo "I am a Mercedes!"; } }
Class Mercedes kế thưà class Car nên nó dĩ nhiên sẽ kế thừa hàm model() đã định nghĩa ở class Car. Vậy theo bạn thì điều gì sẽ xảy ra khi thay vì gọi Car::model(); chúng ta sẽ gọi Mercedes::model() như thế này ? Kết quả sẽ là :
I am a Mercedes!
Không phải đâu, kết quả thật sự vẫn sẽ là
I am a Car
Self
Vậy chuyện gì đã xảy ra ở bên trên ? Chúng ta đã gọi phương thức model() từ class Mercedes cơ mà ? Sao nó vẫn trả về kết quả như khi ta gọi model() từ class Car ? Như ta thấy ở trên, phương thức model() đã định nghĩa ở class Car đã không bị ghi đè trong classs Mercedes. Bởi vì từ khóa self đã tham chiếu đến chính class đã định nghĩa nó (class Car) thay vì class Mercedes hiện tại. Điều này dẫn đến việc nó sẽ gọi hàm getModel() của class Car thay vì gọi đến getModel() của class Mercedes... Trường hợp trên chả phù hợp với tính đa hình trong oop chút nào cả. Class con kế thừa class cha mà không thể nào ghi đè được nó. Và cũng vì vấn đề trên nên từ phiên bản PHP 5.3 trở đi đã cung cấp cho chúng ta một điểm mới gọi là late static bindings
Static và Late static bindings
Bây giờ ở class Car ta thực hiện một thay đổi nho nhỏ. Thay vì dùng từ khóa self ta đổi nó thành static như sau
class Car { public static function model() { static::getModel(); } protected static function getModel() { echo "I am a Car!"; } }
Và thực hiện lại lời gọi hàm Mercedes::model() ta sẽ thấy kết quả trả về như ta mong muốn :
I am a Mercedes!
Đâ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ì khi ta gọi một static funcion, nó sẽ tham chiếu đến class mà nó được gọi thay vì class đã định nghĩa nó như khi ta dùng từ khóa self. Trong trường hợp này, ta gọi model() từ class Mercedes nên nó tham chiếu đến class Mercedes và sẽ gọi đến getModel() của class Mercedess thay vì class Car như ở trường hợp ta sử dụng từ khóa self
Kết luận
Qua bài viết nhỏ trên mình xin phân biệt sự khác nhau giữa "self" và "static" trong PHP. Mong nhận được sự góp ý, chỉnh sửa từ mọi người...