2010-01-09 105 views
5

編輯問題以更好地反映我的需求。調用父類方法


看看下面的例子:

class Base 
{ 
    public $Text = null; 

    public function __construct() 
    { 
     $this->Text = new Base_Text(); 
    } 
} 

class Base_Text extends Base 
{ 
    public $Is = null; 

    public function __construct() 
    { 
     $this->Is = new Base_Text_Is(); 
    } 

    public function CammelCase($string) 
    { 
     return trim(str_replace(' ', '', ucwords($string))); 
    } 
} 

class Base_Text_Is extends Base_Text 
{ 
    public function CammelCase($string) 
    { 
     return ($string === $this->CammelCase($string)); // doesn't work 
    } 
} 

我怎樣才能修復Base_Text_Is::CammelCase()方法,無需調用Base_Text類靜態(不使用parent::Base_Text::)?

我想出了這樣的情況下,唯一的解決方案是創建一個單獨的功能是這樣的:

function Base() 
{ 
    static $instance = null; 

    if (is_null($instance) === true) 
    { 
     $instance = new Base(); 
    } 

    return $instance; 
} 

並更改Base_Text_Is::CammelCase()方法是:

return ($string === Base()->Text->CammelCase($string)); 

而且爲了以避免創建Base類的兩個對象實例,而不是:

$base = new Base(); 
$base->Text->Is->CammelCase('MethodOverloading'); // true 

我只是做:

Base()->Text->Is->CammelCase('MethodOverloading'); // true 

這是一個好的做法呢?還有其他解決方案嗎?

+0

我不在Darrell的回答中得到你最後的評論。你無法訪問'Base_Text'的非靜態屬性?你想從哪裏打電話給他們?我想你應該進一步解釋這一點。 – 2010-01-09 22:24:27

+0

@Felix:我試圖儘可能簡化示例,有些情況下我無法靜態調用父方法,因爲它依賴於實例化的屬性。 – 2010-01-09 22:36:05

回答

7

你的問題的心臟就出在這裏:

如何兒子:: B()調用爸爸:: A() 方法非靜態(不使用 父母或爸爸)?

答案很簡單,它不能。您用Son::A()覆蓋Dad::A()。 Son對象現在唯一的概念A()是它自己的A()。您必須靜態調用父方法,或者使用完全不同的Dad對象實例。

底線是,如果你想打電話給家長A()方法,爲什麼你打擾重寫它在第一個地方?

你的結構也沒有任何意義。你爲什麼要呼叫$dad->A()將它傳遞給$dad->son->A(),而這又會調用$dad->son->B(),然後,從你問的問題中,再次調用$dad->A()?這是一個無限循環。

除了確保您沒有實例化多個父對象之外,您的單例方法似乎沒有提供任何真正的優勢,但事實是您仍在實例化一個完全獨立的對象以執行聽起來像的邏輯它應該在課堂內而不是在外面。

沒有看到實際的邏輯和你想要完成什麼,很難知道推薦什麼來避免這種循環依賴。不過,我想你可能想分析你想用這些方法做什麼,或許重新設計繼承的工作方式。

編輯

我覺得你有太多的方式繼承事情。沒有理由你應該這樣做:

$base = new Base(); 
$base->Text->Is->CammelCase('MethodOverloading'); // true 

如果所有的功能在子類,你不應該實例化Base類。它應該是這樣的:

$text = new Text(); 
$text->isCamelCase('someString'); 

您的代碼可以大大簡化,所有的圓形父/子刪除實例和下推到子類的特定功能:

class Base 
{ 
    //don't put anything related to child classes here, 
    //unless it is going to provide specific functionality 
} 

class Text extends Base 
{ 
    public function CamelCase($string) 
    { 
     return trim(str_replace(' ', '', ucwords($string))); 
    } 

    public function isCamelCase($string) 
    { 
     return ($string === $this->CamelCase($string)); 
    } 
} 
+0

這是一個假設的例子,我知道這是一個無限循環。然而,我遇到了真實世界有用的應用程序,並且我一直使用我在問題中提供的解決方案。我只是想知道是否有更好的選擇。 – 2010-01-09 05:29:28

+0

我已經更新了這個問題,給出了一個更現實的例子,並解決了一些你所提到的問題,比如「實例化一個完全獨立的對象」。希望現在讓它更清晰一點。 – 2010-01-09 05:53:13

+0

@zombat:我想問一下,如果你仍然認爲重新設計繼承是一個好主意(如果是的話,任何指針?),並且如果使用'Base()'單例函數是在這種情況下不好的做法。 – 2010-01-11 07:12:02

1

我不認爲有一種方法可以從靜態調用靜態或使用parent::來調用父級方法。雖然我可能會誤解這個問題。創建Son()的實例不會創建兩個對象。兒子擴大了爸爸,但仍然是一個對象。

如果你打算用Son內的Singleton調用Dad(),那麼爲什麼要從Son中擴展它呢?

+0

我用更實際的例子更新了我的問題,請查看。 – 2010-01-09 05:54:42

+0

我還是不明白你對使用'parent ::'的反感。 – 2010-01-09 06:09:48

+0

這不是一種厭惡,我只是不能使用它,因爲如果我這樣做,我將無法訪問'Base_Text'非靜態屬性。 – 2010-01-09 08:03:39