2012-12-08 71 views
10

Tôi có một lớp cơ sở mà tôi cần gọi các hàm trên một lớp được tham chiếu trong lớp con.Truy cập các biến tĩnh lớp con từ lớp cha?

Dễ dàng đủ,

class base_class { 

    public function doSomethingWithReference(){ 
     $this->reference->doSomething(); 
    } 
} 

class extended_class extends base_class{ 

    protected $reference; 

    public function __construct($ref){ 
     $this->reference = $ref; 
    } 
} 

Bây giờ làm việc này tốt rõ ràng,

Nhưng, khi tôi gỡ lỗi tôi không quan tâm đến giá trị của $this->reference

Tuy nhiên, đối tượng mà $this->reference đề cập đến là rất lớn!

vì vậy, khi tôi làm print_r($instanceOfExtendedClass) Tôi lấy bản in ra khỏi đối tượng đó.

Giờ tham chiếu khác nhau đối với mỗi lớp mở rộng base_class.

Điều tôi muốn làm chỉ là đặt reference làm thuộc tính tĩnh trên lớp extended_class.

Nhưng, sau đó thay đổi doSomethingWithReference thành self::$reference ném lỗi biến không xác định.

Và ngược lại, đặt biến tĩnh trong base_class và sửa đổi nó từ extended_class không hoạt động vì nó thay đổi biến cho tất cả mọi thứ kéo dài từ lớp đó.

Có cách nào để làm điều này vì vậy tôi không nhận được bản in ra khỏi $this->reference?

+2

Bạn đang làm việc với phiên bản PHP nào? Có một số thay đổi [* lớn * đối với hành vi 'tĩnh' trong 5.3] (http://php.net/language.oop5.late-static-bindings), và biết nếu bạn bị mắc kẹt trên thứ gì đó cũ hơn sẽ cung cấp cho bạn một câu trả lời rất khác. – Charles

+1

Phiên bản PHP 5.3 – Hailwood

+0

Cấu trúc lớp này vi phạm điều gì đó, tôi không chắc nó là gì :) –

Trả lời

14

Bởi vì bạn đang sử dụng PHP 5.3, bạn có thể sử dụng late static binding để giải quyết các cuộc gọi tĩnh đến lớp ngay tại thời gian chạy.

class base_class { 

    public function doSomethingWithReference(){ 
     static::$reference->doSomething(); 
    } 

} 

class extended_class extends base_class{ 

    protected static $reference; 

    public function __construct($ref){ 
     static::$reference = $ref; 
    } 

} 

Big nhắc nhở mỡ: Đó là một extended_class::$reference sẽ được chia sẻ giữa tất cả của extended_class trường. Nếu đó không phải là những gì bạn có ý định, điều này sẽ không hoạt động.

Bạn dường như thực sự lo lắng về việc sử dụng bộ nhớ hoặc tài nguyên. Trong PHP, tất cả các đối tượng được truyền bằng tham chiếu. Điều này có nghĩa là truyền một đối tượng làm đối số hoặc tạo bản sao của đối tượng, v.v., không tiêu thụ thêm bộ nhớ. Nếu bạn cần tham chiếu một đối tượng trong một số đối tượng khác, làm như vậy sẽ không tiêu thụ thêm bộ nhớ.


Nếu tôi có extended_class và một lớp giống hệt nhau (nói extended_class1) họ sẽ chia sẻ các tài liệu tham khảo không? hoặc tất cả các cá thể extend_class chia sẻ một tham chiếu, trong khi tất cả các cá thể extended_class1 'sẽ chia sẻ một trường hợp khác (trường hợp lý tưởng)?

Dường như việc chia sẻ dựa trên vị trí biến tĩnh được xác định.Hai ví dụ, cả từ lời nhắc tương tác PHP:

php > class Shared { public $me; public function __construct($me) { $this->me = $me; } } 
php > class Base { protected static $ref; public function foo() { echo static::$ref->me, "\n"; } } 
php > class Inherit_1 extends Base { public function __construct($ref) { static::$ref = $ref; } } 
php > class Inherit_2 extends Base { public function __construct($ref) { static::$ref = $ref; } } 
php > class Inherit_3 extends Inherit_1 {} 
php > $shared_1 = new Shared(1) 
php > ; 
php > $shared_2 = new Shared(2); 
php > $shared_3 = new Shared(3); 
php > 
php > $in_1 = new Inherit_1($shared_1); 
php > $in_2 = new Inherit_2($shared_2); 
php > $in_3 = new Inherit_3($shared_3); 
php > 
php > $in_1->foo(); 
3 
php > $in_2->foo(); 
3 
php > $in_3->foo(); 
3 

Trong trường hợp này, vì tham chiếu sống trong lớp cơ sở, mọi người đều nhìn thấy cùng một lớp. Tôi cho rằng điều này làm cho một số loại ý nghĩa.

Điều gì sẽ xảy ra khi chúng tôi khai báo tham chiếu với từng lớp con .. phần lớn thời gian?

php > class Shared { public $me; public function __construct($me) { $this->me = $me; } } 
php > class Base { public function foo() { echo static::$ref->me, "\n"; } } 
php > class Inherit_1 extends Base { protected static $ref; public function __construct($ref) { static::$ref = $ref; } } 
php > class Inherit_2 extends Base { protected static $ref; public function __construct($ref) { static::$ref = $ref; } } 
php > class Inherit_3 extends Inherit_1 {} 
php > class Inherit_4 extends Inherit_1 { protected static $ref; } 
php > $shared_1 = new Shared(1); 
php > $shared_2 = new Shared(2); 
php > $shared_3 = new Shared(3); 
php > $shared_4 = new Shared(4); 
php > $in_1 = new Inherit_1($shared_1); 
php > $in_2 = new Inherit_2($shared_2); 
php > $in_3 = new Inherit_3($shared_3); 
php > $in_4 = new Inherit_4($shared_4); 
php > $in_1->foo(); 
3 
php > $in_2->foo(); 
2 
php > $in_3->foo(); 
3 
php > $in_4->foo(); 
4 

Vì 3 được kế thừa từ 1 mà không khai báo thuộc tính tĩnh của chính nó, nó được kế thừa 1. Khi chúng ta đặt 3 thành Shared (3), nó sẽ ghi đè lên Shared hiện có của 1 (1).

Kết luận: Để làm việc này, thuộc tính cần được khai báo trong mọi lớp cần tham chiếu duy nhất. Lưu ý rằng mã này có giá trị là 5.4.x.

+0

Tôi không thực sự lo lắng về bộ nhớ, nó chỉ đơn giản là để gỡ lỗi, tôi không thích phải cuộn ~ 600 dòng (Mã Igniter đối tượng!) Để xem những gì các thuộc tính đối tượng được! điểm của bạn về 'extend_class :: $ reference' chia sẻ các tham chiếu, Nếu tôi có' extend_class' và một lớp giống hệt nhau (nói 'extended_class1') thì chúng có chia sẻ tham chiếu không? hoặc tất cả các trường hợp 'extend_class' 'chia sẻ một tham chiếu, trong khi tất cả các cá thể' extended_class1'' sẽ chia sẻ một trường hợp khác (trường hợp lý tưởng)? – Hailwood

+0

@Hailwood, tôi đã cập nhật câu trả lời của tôi với một bài kiểm tra chứng minh nơi tài sản tĩnh được giải quyết. – Charles

2

Cung cấp một cách để phụ huynh để truy cập thành viên tĩnh của trẻ:

<?php 

abstract class base_class { 
    abstract protected function reference(); 
    // If you want to be able to instanciate base class directly, use the following 2 lines in place of the previous 2 lines: 
//class base_class { 
    //protected function reference() {} 

    public function doSomethingWithReference(){ 
     $this->reference()->doSomething(); 
    } 
} 

class extended_class extends base_class{ 
    protected static $reference; 

    public function __construct($ref){ 
     self::$reference = $ref; 
    } 

    protected function reference(){ 
     return self::$reference; 
    } 
} 

class ref { 
    public function doSomething(){ 
     echo __METHOD__; 
    } 
} 

$ref = new ref(); 
$ec = new extended_class($ref); 
$ec->doSomethingWithReference(); 

print_r($ec); 
?> 
+2

-1, đây chỉ là một kết xuất mã. Bạn đã không giải thích mã này là gì, tại sao nó hoạt động, cách nó hoạt động và cách nó trả lời câu hỏi. – Charles

+2

Cảm ơn bạn đã phê bình, @Charles - không có mục đích mỉa mai. Trên thực tế, +1 cho nhận xét của bạn. Trong tương lai, tôi chắc chắn sẽ tiết lộ chi tiết hơn và không cho rằng người đọc sẽ hiểu những gì đang xảy ra chỉ bằng cách đọc mã. Tôi không có một hộp với PHP <5.3 tiện dụng, nhưng tôi tin rằng ví dụ này sẽ làm việc cho những người đang bị mắc kẹt mà không có ràng buộc tĩnh muộn. Khi tôi xác nhận nó hoạt động trong các phiên bản thấp hơn, tôi sẽ cập nhật câu trả lời của mình để giải thích các whys và hows, và nói rằng câu trả lời này có giá trị cho người dùng PHP <5.3. –

Các vấn đề liên quan