Ghi đè hằng số lớp so với thuộc tính


98

Tôi muốn hiểu rõ hơn tại sao, trong trường hợp bên dưới, có sự khác biệt trong cách các hằng số lớp được kế thừa so với các biến cá thể.

<?php
class ParentClass {
    const TEST = "ONE";
    protected $test = "ONE";

    public function showTest(){
        echo self::TEST;
        echo $this->test;
    }
}

class ChildClass extends ParentClass {
    const TEST = "TWO";
    protected $test = "TWO";

    public function myTest(){
        echo self::TEST;
        echo $this->test;
    }
}

$child = new ChildClass();
$child->myTest();
$child->showTest();

Đầu ra:

TWO
TWO
ONE
TWO

Trong đoạn mã trên, ChildClass không có phương thức showTest (), vì vậy phương thức showTest () của ParentClass được sử dụng theo phương thức kế thừa. Kết quả cho thấy rằng vì phương thức đang thực thi trên ParentClass, phiên bản ParentClass của hằng số TEST đang được đánh giá, trong khi vì nó đang đánh giá trong ngữ cảnh ChildClass thông qua kế thừa, biến thành viên ChildClass $ test đang được đánh giá.

Tôi đã đọc tài liệu, nhưng dường như không thấy bất kỳ đề cập nào về sắc thái này. Bất cứ ai có thể làm sáng tỏ cho tôi?


WTF? Ghi đè liên tục !? Đừng làm điều này! không bao giờ!
qwert_ukg

2
@qwert_ukg Thật vậy. Ai đó nên thông báo điều đó cho các nhà phát triển PHP. Hoặc ít nhất là cho phép final...
Luke Sawczak

1
Chắc chắn có những trường hợp sử dụng đủ tốt ngay cả khi ghi đè liên tục:]
Arziel

Câu trả lời:


193

self::Không nhận thức được kế thừa và luôn đề cập đến lớp mà nó đang được thực thi. Nếu bạn đang sử dụng php5.3 +, bạn có thể thử static::TESTnhưstatic:: nhận biết kế thừa.

Sự khác biệt là static::sử dụng "liên kết tĩnh muộn". Tìm thêm thông tin tại đây:

http://php.net/manual/en/language.oop5.late-static-bindings.php

Đây là một kịch bản thử nghiệm đơn giản mà tôi đã viết:

<?php

class One
{
    const TEST = "test1";

    function test() { echo static::TEST; }
}
class Two extends One
{
    const TEST = "test2";
}

$c = new Two();

$c->test();

đầu ra

test2

22
+ để đề cập static::.
Jason McCreary

Tuyệt vời. Cảm ơn bạn đã làm rõ và cung cấp thông tin bổ sung về các liên kết tĩnh muộn (mà tôi vẫn chưa hiểu).
Tom Auger

3
test()không phải là một phương thức tĩnh, tại sao không sử dụng $this::TESTvới PHP5.3 +?
Xenos

Xin chào @Xenos - Mục tiêu của ví dụ là cho thấy rằng mã cấp phiên bản thực thi trong lớp Một đang truy xuất các giá trị tĩnh từ lớp Hai. self :: TEST sẽ trả về "test1" trong đó static :: TEST trả về "test2" được mong đợi - Hy vọng điều đó sẽ hữu ích, cảm ơn bạn đã trả lời!
David Farrell

Xin chào @DavidFarrell - Có, tôi có self::/ static::sự khác biệt nhưng tôi không hiểu tại sao lại sử dụng static::thay vì $this::(không phải self::). Có sự khác biệt giữa $this::static::(vì có một giữa static::/ $this::self::) không?
Xenos

16

Trong PHP, self đề cập đến lớp trong đó phương thức hoặc thuộc tính được gọi được định nghĩa. Vì vậy, trong trường hợp của bạn, bạn đang gọi điện thoại selftrong ChildClass, vì vậy nó sử dụng các biến từ lớp đó. Sau đó, bạn sử dụng selftrongParentClass , vì vậy nó sẽ tham chiếu đến biến trong lớp đó.

nếu bạn vẫn muốn lớp con ghi đè constlớp cha, thì hãy điều chỉnh mã sau trong lớp cha của bạn thành mã này:

public function showTest(){
    echo static::TEST;
    echo $this->test;
}

Lưu ý static từ khóa. Điều này sử dụng "liên kết tĩnh muộn". Bây giờ bạn là lớp cha sẽ gọi const của lớp con của bạn.


chuyên nghiệp. tĩnh :: làm việc trong trừu tượng thay vì tự ::
Błażej Krzakala
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.