2011-05-27 40 views
2

簡而言之:一個類從父類繼承了一個函數。然後該函數被調用,但似乎仍然具有父類類的範圍。這是預期的行爲?奇怪的PHP的oop行爲,有人可以解釋嗎?

考慮下面的代碼示例:

<?php 
class OLTest { 
    private $var1 = 10; 

    public function getVar1() { 
     if (isset($this->var1)) { 
      return $this->var1; 
     } else { 
      return 'undefined'; 
     } 
    } 

    public function getVar2() { 
     if (isset($this->var2)) { 
      return $this->var2; 
     } else { 
      return 'undefined'; 
     } 
    } 
} 

class OLTest2 extends OLTest { 
    private $var1 = 11; 
    private $var2 = 20; 
} 

$oltest = new OLTest(); 
$oltest2 = new OLTest2(); 

echo "calling parent->getVar1\n"; 
echo $oltest->getVar1() . "\n"; 

echo "calling parent->getVar2\n"; 
echo $oltest->getVar2() . "\n"; 

echo "calling child->getVar1\n"; 
echo $oltest2->getVar1() . "\n"; 

echo "calling child->getVar2\n"; 
echo $oltest2->getVar2() . "\n"; 
?> 

據我瞭解,輸出應該是:

calling parent->getVar1 
10 
calling parent->getVar2 
undefined 
calling child->getVar1 
11 
calling child->getVar2 
20 

我的機器上的實際輸出爲

calling parent->getVar1 
10 
calling parent->getVar2 
undefined 
calling child->getVar1 
10 
calling child->getVar2 
undefined 

要添加在這兩個函數中的一個print_r($this)混淆,將顯示範圍我實際上設置爲子類,但是不可能訪問變量。

有人可以幫我解決這個問題嗎?

編輯:我在版本5.3.3-1ubuntu9.5中使用PHP。

+0

哪個版本的PHP? – 2011-05-27 14:35:17

+0

忘了這一點。其5.3.3。 – 2011-05-27 14:37:20

+0

添加爲檢查isset和返回值或未定義的簡單方法 – 2011-05-27 14:52:13

回答

4

不,輸出應該定義爲10, undefined, 10, undefined。 原因是private的變量僅對定義它們的類(不是超類或子類)纔可見。

所以,當child被調用,其方法是在父對象定義,當他們解決var1var2他們definied爲OLTest範圍檢查。 var2也無法訪問,因爲聲明的var2僅在OLTest2中可見。

要得到您的輸出結果,您應該聲明這些變量protectedpublic

+0

好吧謝謝。似乎我需要梳理我的oop一點:) – 2011-05-27 14:45:57

+0

我知道這是來自PHP團隊的OOP實施決策 - 不是絕對的OOP規則。也許我錯了,但我就是這麼看的。 – 2011-05-27 14:51:03

1

您不能將private $var2「注入」父類,這正是您要做的。 所以是的,這是正常的行爲。

+0

那麼當我將變量範圍更改爲受保護時它是如何工作的? – 2011-05-27 14:41:06

2

它似乎與private範圍有關。

嘗試更改爲protectedpublic並檢查結果。

+0

更改變量作用域可修復此問題。但不應該繼承的方法首先與子類的範圍執行? – 2011-05-27 14:40:35

+0

看來這個方法運行在「類內」而不是「在實例內」。在這種情況下,即使「$ oltest2」(實例)是「OLTest2」對象,「OLTest」(類)也不能看到「var2」,並且只能看到它自己的「var1」... – 2011-05-27 14:49:01

1

因爲你已經聲明你的變量是私有的,它們是完全彼此隱藏的。因此,在父$var1實際上是從孩子$var1不同的變量

當你的父母打電話getVar1,它使用它看到$var1,一個來自父和值10同樣,家長可以不看到孩子的$var2,所以它的屬性是未定義的。

當你的孩子叫getVar1getVar2,該方法本身是從父類繼承,準確地表現爲他們,如果他們從類型的對象稱爲OLTest

2

是的,那是因爲你屬性是私人的。您正在調用的方法仍然屬於父類,因爲您尚未重新定義它們。啓用父方法訪問孩子的屬性,你必須讓他們protected在兩家母公司和子類:

class OLTest { 
    protected $var1 = 10; 

    public function getVar1() { 
     if (isset($this->var1)) { 
      return $this->var1; 
     } else { 
      return 'undefined'; 
     } 
    } 

    public function getVar2() { 
     if (isset($this->var2)) { 
      return $this->var2; 
     } else { 
      return 'undefined'; 
     } 
    } 
} 

class OLTest2 extends OLTest { 
    protected $var1 = 11; 
    protected $var2 = 20; 
} 

如果你把它private在父類它不會讓子類重寫該屬性,所以功能屬於父母課程將訪問自己的私人財產。如果你在子類中使它是私有的,它將不允許父方法訪問它。

如果你仍然想保持它們的私密性,你必須將你的方法的代碼複製粘貼到子類中(是的,return parent::getVar1()也不適用)。

0

這是你的私有變量的範圍,嘗試使用受保護的

class OLTest { 
    protected $var1 = 10; 

    public function getVar1() { 
     return isset($this->var1) ? $this->var1:'undefined'; 
    } 

    public function getVar2() { 
     return isset($this->var2) ? $this->var2:'undefined'; 
    } 
} 

class OLTest2 extends OLTest { 
    protected $var1 = 11; 
    protected $var2 = 20; 
} 

$oltest = new OLTest(); 
$oltest2 = new OLTest2(); 

echo "calling parent->getVar1\n".$oltest->getVar1()."\n"; 
echo "calling parent->getVar2\n".$oltest->getVar2()."\n"; 
echo "calling child->getVar1\n".$oltest2->getVar1()."\n"; 
echo "calling child->getVar2\n".$oltest2->getVar2()."\n"; 

結果:

calling parent->getVar1 
10 
calling parent->getVar2 
undefined 
calling child->getVar1 
11 
calling child->getVar2 
20 
相關問題