2012-12-08 184 views
10

我有一個基類,我需要調用子類中引用的類的函數。從父類訪問子類靜態變量?

很容易的,

class base_class { 

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

class extended_class extends base_class{ 

    protected $reference; 

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

現在這個工作顯然很好,

但是,當我調試,我不關心$this->reference

值只是,對象$this->reference指的是巨大的!

所以,當我做print_r($instanceOfExtendedClass)我打印出來的對象。

現在,每個延伸base_class的類的參考都不相同。

我想要做的就是將reference設置爲extended_class類的靜態屬性。

但是,然後更改doSomethingWithReferenceself::$reference將引發未定義的變量錯誤。

反過來,在base_class中設置靜態變量並將其從extended_class修改爲靜態變量不起作用,因爲它會更改從該類延伸的所有內容的變量。

有沒有辦法做到這一點,所以我沒有打印出$this->reference

+2

你正在使用哪個PHP版本?在[5.3]中有一些[* static]行爲的巨大變化](http://php.net/language.oop5.late-static-bindings),並且知道你是否被卡在老的東西上會給你一個非常不同的答案。 – Charles

+1

PHP版本5.3 – Hailwood

+0

此類結構違反了某些內容,我只是不確定它是什麼:) –

回答

14

因爲你正在使用PHP 5.3,你可以使用late static binding解決在運行時正確類靜態調用。

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; 
    } 

} 

大胖提醒:那一個extended_class::$reference將要之中extended_class實例的所有共享。如果這不是你想要的,這是行不通的。

你似乎實際上擔心內存或資源的使用。在PHP中,所有對象都通過引用傳遞。這意味着傳遞一個對象作爲參數,或創建它的一個副本等,不會消耗額外的內存。如果您需要引用多個其他對象中的對象,則這樣做會使而不是消耗額外的內存。


如果我有extended_class和另一個相同的類(比如extended_class1)將他們共用參考呢?或者所有extended_class'實例共享一個引用,而所有extended_class1'實例將共享另一個(理想情況)?

它看起來像共享是基於靜態變量的定義。有兩個例子,無論是從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 

在這種情況下,因爲參考生活在基類中,每個人看到的相同。我想這是有道理的。

當我們爲每個孩子類聲明參考時會發生什麼?大部分時間?

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 

因爲3從1繼承而沒有聲明它自己的靜態屬性,所以它繼承了1。當我們將3設置爲共享(3)時,它覆蓋了1的現有共享(1)。

結論:爲此,該屬性需要在中聲明,每類需要唯一的唯一引用。請注意,此代碼自5.4.x起生效。

+0

我實際上並不擔心內存,它只是用於調試,我不喜歡滾動600行(代碼點火器對象!)來查看對象屬性是什麼!你有關'extended_class :: $ reference'共享引用的觀點,如果我有'extended_class'和另一個相同的類(比如'extended_class1'),他們是否也會共享引用?或者所有'extended_class''實例共享一個引用,而所有'extended_class1''實例將共享另一個(理想情況)? – Hailwood

+0

@Hailwood,我已經用一個測試來更新我的答案,演示靜態屬性的解決方法。 – Charles

2

提供一種方式,父訪問孩子的靜態成員:

<?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,這只是一個代碼轉儲。你還沒有解釋這個代碼是什麼,它爲什麼有效,它是如何工作的以及它如何回答這個問題。 – Charles

+2

感謝批評,@Charles--沒有諷刺意圖。實際上,您的評論+1。將來,我一定會更加冗長,而不是假設讀者通過閱讀代碼就能理解正在發生的事情。我沒有一個PHP <5.3的方塊,但我相信這個例子可以用於那些沒有延遲靜態綁定的情況。一旦我確認它在較小的版本中工作,我會更新我的答案以解釋原因和希望,並聲明這個答案對PHP <5.3的用戶有價值。 –