2012-07-09 97 views
0

我一直在研究PHP 5.3.x中跟隨Active Record模式的一小組類。但是,在處理靜態屬性時,我遇到了一個問題。這裏的代碼位我一直在測試這個:一個類中的靜態屬性由另一個設置

<?php 

class dbPreparedObject { 

    public static $insert = ""; 

    public function __construct() { 
     static::$insert = "autoinsert_".get_called_class(); 
    } 
} 

class gtRecord extends dbPreparedObject {} 
class nRecord extends dbPreparedObject {} 

$a = new gtRecord(); 
$b = new nRecord(); 

var_dump(gtRecord::$insert); 
var_dump(nRecord::$insert); 

輸出:

string(18) "autoinsert_nRecord" 
string(18) "autoinsert_nRecord" 

但是,我想到的第一個字符串讀autoinsert_gtRecord

似乎沒有由子類實例化的靜態屬性被綁定在一起。如果沒有在每個孩子課堂上申報public static $insert = "",有什麼辦法將他們分開?

回答

1

這是預期的行爲。在PHP中,聲明爲靜態的屬性在創建的對象的所有實例中共享。也就是說,在dbPreparedObject或其繼承的類的所有實例中只有一個$insert的實例。

您看到autoinsert_nRecord的原因都是var_dump s是因爲那是您創建的最後一個對象。

考慮這個微小的變化:

$a = new gtRecord(); 
var_dump(gtRecord::$insert); // autoinsert_gtRecord 

$b = new nRecord();  
var_dump(nRecord::$insert); // autoinsert_nRecord 
var_dump(gtRecord::$insert); // autoinsert_nRecord (because it was the last one set) 

第一的var_dump後,該值是_gtRecord,但是一旦被創建nRecord對象,靜態屬性,都會因爲這改變了(所有dbPreparedObject對象)是nRecord是最後一堂課。

所以,如果你打算在具有此類的多個實例,$insert不能是靜態的,因爲它不會總是包含您所期望給予代碼​​的價值,因爲在靜態$insert財產只有一個副本是所有相同對象。一旦你在一個對象中改變它,你可以在所有對象中改變它。

所以我們需要問爲什麼$insert需要是靜態的或者你有什麼其他的選擇,所以你不會遇到這個問題。

+0

我想我的問題是如何定義應該由類繼承的屬性,而無需在類聲明中明確定義它們? – grobolom 2012-07-09 16:28:15

+0

如果某個屬性是公共的或受保護的,它將由任何子類繼承,而不在子類中定義它們。 – drew010 2012-07-09 18:08:23

+0

對我來說,看起來很奇怪,如果我在一個子類中正確地繼承了一個繼承,那麼它會影響其他子類中的繼承。爲什麼繼承或不繼承的子類的屬性會影響父類? – grobolom 2012-07-09 18:39:21

相關問題