2009-12-16 44 views

Trả lời

67

Tính đến PHP 5.3.0, PHP thực hiện một tính năng gọi là cuối tĩnh ràng buộc mà có thể được sử dụng để tham khảo các lớp được gọi là trong bối cảnh thừa kế tĩnh.

Kết thúc cố định trễ cố gắng giải quyết giới hạn đó bằng cách giới thiệu từ khóa tham chiếu đến lớp ban đầu được gọi là thời gian chạy. Nó đã được quyết định không giới thiệu một từ khóa mới, nhưng thay vì sử dụng static đã được bảo lưu.

Chúng ta hãy xem một ví dụ:

<?php 
    class Car 
    { 
     public static function run() 
     { 
      return static::getName(); 
     } 

     private static function getName() 
     { 
      return 'Car'; 
     } 
    } 

    class Toyota extends Car 
    { 
     public static function getName() 
     { 
      return 'Toyota'; 
     } 
    } 

    echo Car::run(); // Output: Car 
    echo Toyota::run(); // Output: Toyota 
?> 

late static bindings công việc bằng cách lưu trữ các lớp có tên trong "cuộc gọi không chuyển tiếp" cuối cùng. Trong trường hợp các cuộc gọi phương thức tĩnh, đây là lớp được đặt tên rõ ràng (thường là lớp bên trái của toán tử ::); trong trường hợp các cuộc gọi phương thức không tĩnh, nó là lớp của đối tượng.

"Cuộc gọi chuyển tiếp" là một cuộc gọi chuyển tiếp được giới thiệu bởi self::, parent::, static:: hoặc, nếu đi lên trong hệ thống phân cấp lớp, forward_static_call().

Chức năng get_called_class() có thể được sử dụng để truy xuất chuỗi có tên của lớp được gọi và static:: giới thiệu phạm vi của nó.

158

Bạn chắc chắn cần đọc Late Static Bindings trong hướng dẫn sử dụng PHP. Tuy nhiên, tôi sẽ cố gắng cung cấp cho bạn một bản tóm tắt nhanh.

Về cơ bản, từ khóa này tuân theo thực tế là từ khóa self không tuân thủ các quy tắc thừa kế. self luôn phân giải tới lớp mà nó được sử dụng. Điều này có nghĩa rằng nếu bạn thực hiện một phương thức trong một lớp cha và gọi nó từ một lớp con, self sẽ không tham chiếu đến đứa trẻ như bạn mong đợi.

Ràng buộc tĩnh muộn giới thiệu cách sử dụng mới cho từ khóa static, giải quyết sự thiếu hụt cụ thể này. Khi bạn sử dụng static, nó đại diện cho lớp mà bạn sử dụng lần đầu tiên, ví dụ: nó 'liên kết' với lớp thời gian chạy.

Đó là hai khái niệm cơ bản đằng sau nó. Cách self, parentstatic hoạt động khi static hoạt động có thể tinh tế, vì vậy thay vì đi sâu vào chi tiết hơn, tôi thực sự khuyên bạn nên nghiên cứu các ví dụ về trang thủ công. Một khi bạn hiểu những điều cơ bản của mỗi từ khóa, các ví dụ là khá cần thiết để xem loại kết quả bạn sẽ nhận được.

+24

+1 Mô tả của bạn là đơn giản và rõ ràng so với cái được tìm thấy trong PHP thủ công. – Mouli

+2

đây phải là câu trả lời được chấp nhận. nó đơn giản và hữu ích –

+0

tôi thấy bài viết này thực sự hữu ích và mô tả, kiểm tra xem nó ra [link] (https://www.techflirt.com/tutorials/oop-in-php/late-static-binding.html) –

4

Ví dụ:

abstract class Builder { 
    public static function build() { 
     return new static; 
    } 
} 

class Member extends Builder { 
    public function who_am_i() { 
     echo 'Member'; 
    } 
} 

Member::build()->who_am_i(); 
20

Không có hành vi rất rõ ràng:

Mã sau đây tạo 'alphabeta'.

class alpha { 

    function classname(){ 
     return __CLASS__; 
    } 

    function selfname(){ 
     return self::classname(); 
    } 

    function staticname(){ 
     return static::classname(); 
    } 
} 

class beta extends alpha { 

    function classname(){ 
     return __CLASS__; 
    } 
} 

$beta = new beta(); 
echo $beta->selfname(); // Output: alpha 
echo $beta->staticname(); // Output: beta 

Tuy nhiên, nếu chúng tôi xóa khai báo hàm lớp khỏi lớp beta, chúng tôi sẽ nhận được 'alphaalpha'.

+1

Thật thú vị . Tôi phải kiểm tra bản thân mình – instead

+1

Rất đẹp. Điều tương tự cũng được hiển thị trong hướng dẫn sử dụng PHP, nhưng điều này rõ ràng hơn nhiều. Để tham khảo: http://php.net/manual/en/language.oop5.late-static-bindings.php (xem ví dụ 4) – musicin3d

9

Tôi trích dẫn từ cuốn sách: "PHP Master viết mã cắt cạnh".

Kết buộc tĩnh muộn là tính năng được giới thiệu với php 5.3. Nó cho phép chúng tôi kế thừa các phương thức tĩnh từ một lớp cha và để tham chiếu lớp con được gọi.

Điều này có nghĩa bạn có thể có một lớp trừu tượng với phương pháp tĩnh, và triển khai cụ thể tham khảo các lớp con của bằng tĩnh ::() phương pháp ký hiệu thay vì tự ::() phương pháp.

Hãy thoải mái để có một cái nhìn tại các tài liệu php chính thức cũng như: http://php.net/manual/en/language.oop5.late-static-bindings.php

Ví dụ:

<?php 
class Animal { 
    public static function StaticCall() { 
     // Parent object invokes its own getAnimalName() 
     // Child object invokes its own getAnimalName() instead of parent's getAnimalName() 
     return static::getAnimalName(); 
    } 

    public static function SelfCall() { 
     return self::getWeight(); 
    } 

    private static function getAnimalName(){ 
     return 'Animal <br />'; 
    } 

    private static function getWeight(){ 
     return '10 kg <br />'; 
    } 
} 

class Bird extends Animal { 
    public static function getAnimalName(){ 
     return 'Bird <br />'; 
    } 

    private static function getWeight(){ 
     return '2 kg <br />'; 
    } 
} 

echo Animal::StaticCall(); // Animal  
echo Animal::SelfCall(); // 10 kg   
echo Bird::StaticCall(); // Bird invokes method from own object 
echo Bird::SelfCall();  // 10 kg invokes method from parent 

Trong đoạn mã trên bạn có thể thấy hai lớp Animal đó là tầng lớp phụ huynh và Bird là lớp con. Cả hai số AnimalBird đều có phương thức getAnimalName()getWeight(). Siêu lớp Animal có hai phương pháp: StaticCall()SelfCall().

Phương thức StaticCall() gọi getAnimalName() bằng cách sử dụng từ khóa static.
Phương thức SelfCall() gọi getWeight() bằng cách sử dụng từ khóa self .

Câu hỏi mà chúng tôi hiện có là: trong đó ngữ cảnh là getAnimalName() được thực thi?

Câu trả lời: static::getAnimalName() xác định ngữ cảnh và gọi phương thức trong ngữ cảnh đó.

Nếu bạn gọi Bird::StaticCall() mã sẽ thực hiện StaticCall() có trong Animal. Sau đó, static::getAnimalName() sẽ gọi và thực hiện từ Bird phương thức getAnimalName().

Điều này khác với self::, vì self:: luôn gọi phương pháp này trong đối tượng self được định nghĩa trong. Vì vậy, nếu self::getWeight() được định nghĩa trong đối tượng Animal trong phương pháp SelfCall()Bird::SelfCall() sẽ được gọi sau đó self::getWeight() gọi getWeight() trong bối cảnh của đối tượng Animal .

4

Nhìn vào từ "lý do tại sao tôi nên sử dụng tính năng này?" quan điểm, về cơ bản nó là một cách để thay đổi bối cảnh mà từ đó phương thức tĩnh đang được hiểu/chạy.

Với self, ngữ cảnh là ngữ cảnh mà bạn đã xác định phương thức ban đầu. Với static, đó là số bạn đang gọi.

7

Ví dụ đơn giản nhất để hiển thị sự khác biệt.
Note, tự :: $ c

class A 
{ 
    static $c = 7; 

    public static function getVal() 
    { 
     return self::$c; 
    } 
} 

class B extends A 
{ 
    static $c = 8; 
} 

B::getVal(); // 7 

Cuối tĩnh ràng buộc, lưu ý tĩnh :: $ c

class A 
{ 
    static $c = 7; 

    public static function getVal() 
    { 
     return static::$c; 
    } 
} 

class B extends A 
{ 
    static $c = 8; 
} 

B::getVal(); // 8 
Các vấn đề liên quan