Hướng dẫn method overriding in php

Tải chồng trong PHP mang nghĩa tạo các thuộc tính và phương thức động. Những thành phần động này được xử lý thông qua các magic method được thiết lập trong một lớp với các kiểu hành động khác nhau.

Các phương thức tải chồng được gọi khi tương tác với các thuộc tính và phương thức không được khai báo hay không xuất hiện trong lớp hiện thời. Bài viết này sẽ sử dụng khai niệm "thuộc tính không thể truy cập" và "phương thức không thể truy cập" để tham chiếu tới sự kết hợp của khai báo và tầm vực.

Tất các các phương thức tải chồng phải được khai báo là public.

Chú ý:

Các tham số của các phương thức magic không được truyền bằng tham chiếu.

Khái niệm "tải chồng" của PHP khác so với phần lớn các ngôn ngữ lập trình hướng đối tượng khác. Khai niệm tải chồng truyền thống là cho phép nhiều phương thức cùng tên trong một lớp nhưng khác nhau về số lượng và kiểu của tham số.

Tải chồng thuộc tính

public void __set ( string $name , mixed $value )

public mixed __get ( string $name )

public bool __isset ( string $name )

public void __unset ( string $name )

__set() được thực thi khi ghi dữ liệu tới thuộc tính không thể truy cập.

__get() được thực thi khi đọc dữ liệu từ thuộc tính không thể truy cập.

__isset() được kích hoạt bằng cách gọi isset() hoặc empty() ở những thuộc tính không thể truy cập.

__unset() được gọi đến khi unset() được sử dụng ở nhưng thuộc tính không thể truy cập.

Tham số $name là tên của thuộc tính muốn tương tác. Tham số $value của phương thức __set() xác định giá trị của thuộc tính $name được thiết lập.

Tải chồng thuộc tính chỉ làm việc với đối tượng. Những magic methods này sẽ không được kích hoạt trong trường hợp static context. Do đó những phương thức này không được khai báo là static. Ở phiên bản PHP 5.3.0 thì một cảnh báo sẽ được đưa ra nếu một sự tải chồng của magic method nào đó được khai báo là static.

Chú ý:

Giá trị trả về của __set() bị bỏ qua bởi cách thức PHP xử lý toán tử gán. Tương tự như vậy thì phương thức __get() sẽ không bao giờ được gọi khi ta thực hiện việc gán liên tiếp dạng như sau:

$a = $obj->b = 8;

Dưới đây là ví dụ về tải chồng thuộc tính thông qua các phương thức __get(), __set(), __isset() và __unset()


class PropertyTest
{
    
/**  Nơi tải chồng dữ liệu.  */
    
private $data = array();/**  Tải chồng không sử dụng thuộc tính đã khai báo.  */
    
public $declared 1;/**  Tải chồng chỉ sử dụng khi truy cập ngoài lớp.  */
    
private $hidden 2;

    public function

__set($name$value)
    {
        echo 
"Thiết lập '$name' = '$value'\n";
        
$this->data[$name] = $value;
    }

    public function

__get($name)
    {
        echo 
"Lấy '$name'\n";
        if (
array_key_exists($name$this->data)) {
            return 
$this->data[$name];
        }
$trace debug_backtrace();
        
trigger_error(
            
'Không định nghĩa thuộc tính thông qua __get(): ' $name .
            
' trong ' $trace[0]['file'] .
            
' tại dòng ' $trace[0]['line'],
            
E_USER_NOTICE);
        return 
null;
    }
/**  Phiên bản PHP 5.1.0  */
    
public function __isset($name)
    {
        echo 
"'$name' được thiết lập?\n";
        return isset(
$this->data[$name]);
    }
/**  Phiên bản PHP 5.1.0  */
    
public function __unset($name)
    {
        echo 
"Không thiết lập '$name'\n";
        unset(
$this->data[$name]);
    }
/**  Đây không phải là magic method.  */
    
public function getHidden()
    {
        return 
$this->hidden;
    }
}

echo

"
\n";

$obj = new PropertyTest;

$obj->1;
echo 
$obj->"\n\n";

var_dump(isset($obj->a));
unset(
$obj->a);
var_dump(isset($obj->a));
echo 
"\n";

echo

$obj->declared "\n\n";

echo

"Thử nghiệm với phương thức private có tên 'hidden':\n";
echo 
"Private xuất hiện trong lớp, nên __get() không được sử dụng...\n";
echo 
$obj->getHidden() . "\n";
echo 
"Private không xuất hiện ngoài lớp, nên __get() được sử dụng...\n";
echo 
$obj->hidden "\n";
?>

Output của ví dụ trên:

Thiết lập 'a' = '1'
Lấy 'a'
1

'a' được thiết lập?
bool(true)
Không thiết lập 'a'
'a' được thiết lập?
bool(false)

1

Thử nghiệm với phương thức private có tên 'hidden':
Private xuất hiện trong lớp, nên __get() không được sử dụng...
2
Private không xuất hiện ngoài lớp, nên __get() được sử dụng...
Lấy 'hidden'

Notice:  Thuộc tính không định nghĩa thông qua __get(): hidden trong tại dòng 70 trong tại dòng 29

Tải chồng phương thức

public mixed __call ( string $name , array $arguments )

public static mixed __callStatic ( string $name , array $arguments )

__call() được kích hoạt khi gọi phương thức không thể truy cập của đối tượng.

__callStatic() được kích hoạt khi gọi phương thức không thể truy cập trong phạm vi static.

Tham số $name là tên của phương thức được gọi. Tham số $arguments là một mảng chứa các tham số được truyền tới phương thức có tên $name.

Ví dụ sau nói về các phương thức tải chồng __call() và __callStatic()


class MethodTest
{
    public function 
__call($name$arguments)
    {
        
// Lưu ý: giá trị của $name là phân biệt hoa/thường.
        
echo "Gọi phương thức '$name' "
             
implode(', '$arguments). "\n";
    }
/**  PHP 5.3.0  */
    
public static function __callStatic($name$arguments)
    {
        
// Lưu ý: giá trị của $name phân biệt hoa/thường.
        
echo "Gọi phương thức static '$name' "
             
implode(', '$arguments). "\n";
    }
}

$obj = new MethodTest;
$obj->runTest('trong đối tượng');

MethodTest::runTest('trong trường hợp static');  // PHP 5.3.0
?>

Output của đoạn mã trên:

Gọi phương thức 'runTest' trong đối tượng
Gọi phương thức tĩnh 'runTest' trong trường hợp static