2011-06-14 107 views
21

當我嘗試重寫類變量的方式與重寫PHP中的類方法的方式相同。如:PHP變量覆蓋

class DataMapper { 
    protected $_name = null; 

    public function printName() { 
      echo $this->_name; 
    } 
} 

class Model extends DataMapper { 
    protected $_name = 'Ana'; 
} 

$test = new Model(); 
$test->printName(); 

這是打印'安娜'。

爲什麼PHP可以做這樣的事情呢?它打破了面向對象範式的規律

+1

我不認爲語言行爲在任何司法管轄區都是非法的。變量實際上不需要被映射。而在PHP中,對象也是非常簡單的字典。你只在這裏重新聲明默認值。 – mario 2011-06-14 04:56:36

+5

那些不是類變量(即'static'),它們是對象/實例變量。正如人們所解釋的,這就是繼承應該如何與受保護的成員一起工作。如果你想設置一個私有類變量(即'private static $ myVar ='Ana';'),那麼它就不會在任何子類中定義。 – joelhardi 2011-06-14 05:11:04

+0

我理解它的方式,你是對的。您通常不能覆蓋變量。在這裏,你並沒有真的這麼做,你只是簡單地重新宣佈一個變量,而原來的東西卻丟失了。反正我覺得呢。 我認爲PHP的標準只是稍微寬鬆一些,並且可以讓您擺脫可疑的語法/操作。 – Jonathon 2013-04-17 01:59:20

回答

25

不是。這就是PHP應該如何工作。看看PHP Classes and Objects Visibility

即使它們不是相同的實例,同一類型的對象也可以訪問其他私有和受保護的成員。這是因爲實現特定的細節在這些對象內部時是已知的。

由於Model擴展了DataMapper,它可以訪問它的函數,變量等,但它可以覆蓋它們發生的情況。雖然您的函數存在於DataMapper類中,但它是從名稱設置爲Ana的Model類調用的(並由其繼承)。

+0

哇真的很好的答案,我不知道如果PHP可以做到這一點。我已經嘗試了C++,C#和JAVA中的相關代碼,但沒有運氣 – brian 2011-06-14 05:06:36

+0

@brian,PHP可以做到這一點,這是一種允許變量覆蓋的語言; Java只支持變量隱藏,所以你會得到不同的結果。 – MengT 2014-10-02 08:00:01

3

我不認爲這打破了「面向對象的規律」。你已經繼承了DataMapper類。因此你已經繼承了公共函數printName()。所以當你調用函數時,它就像屬於模型類的函數一樣。

4

我認爲你只是無法理解這是什麼。當你引用$ this時,它實際上是引用當前對象。

當您繼承DataMapper類時,可以在Model對象內訪問printName()方法,但$ this引用仍然引用當前Model對象$ test。

由於Model對象的$ _name屬性被實例化爲「Ana」,因此它正在打印Ana。這正是預期的。也許再讀一遍繼承和範圍的理論可以幫助你理解這裏發生的事情。

+0

是的,但在其他語言像c + +,c#和java它不能這樣做。我的意思是覆蓋類變量 – brian 2011-06-14 05:12:15

+1

@brian in c#你可以,你只需要明確你打算重寫它。否則它只是向下隱藏該範圍的父變量。在PHP中的區別是'override'是隱含的。 – drzaus 2013-06-16 19:40:31