2010-11-13 46 views

回答

2

Like deceze already points out,這是不可能的繼承。

你可以使用PECL的runkit_class_adopt基類轉換爲繼承的類,添加祖傳方法在適當的時候但runkit是你不想東西在你的產品代碼。

清潔OO方法這是使用一個Bridge pattern,得到對象在運行時在A類的實現,並由此

解耦從它的實現的抽象,使得可以獨立地變化。

它是如何工作

首先定義一個接口B和B本身來實現的每一個「父」。界面應該包含你想要B「繼承」的所有方法。我將這些術語放在引號中,因爲從技術上講,它們既不是父母,也不是繼承任何東西。

interface MyImplementation 
{ 
    public function doSomething(); 
    // more methods … 
} 

然後定義實現此接口的類A1和A2並添加接口要求的方法。

class A1 implements MyImplementation 
{ 
    public function doSomething() 
    { 
     return 'A1'; 
    } 
    // more methods … 
} 
class A2 implements MyImplementation 
{ 
    public function doSomething() 
    { 
     return 'A2'; 
    } 
    // more methods … 
} 

接下來,建立B類,並使其需要在初始化的實現類之一。

abstract class B implements MyImplementation 
{ 
    protected $_implementation; 
    // more properties ... 

    public function __construct(MyImplementation $implementationObj) 
    { 
     $this->_implementation = $implementationObj; 
    } 
    public function doSomething() 
    { 
     return $this->_implementation->doSomething(); 
    } 
    // more methods ... 
} 

正如你所看到的,通過我們的接口所需要的方法的任何調用都被委託給聚集的「父」對象,所以這取決於你傳遞到B,你會得到不同的結果。

現在定義C,我們只是讓它接受實現類的類名並在C中實例化它以將其傳遞給父類, B.

class C extends B { 
    public function __construct($bMethodImplementation) { 
     parent::__construct(new $bMethodImplementation); 
    } 
} 

,然後你可以做

$c = new C('A1'); 
echo $c->doSomething(); // echoes A1 
$c = new C('A2'); 
echo $c->doSomething(); // echoes A2 
4

既然你需要對父類進行硬編碼(class B extends A1),這是不可能的(儘管運行時擴展/黑客,我不會推薦進入)。如果您需要這種靈活性,請考慮composition而不是繼承。

+0

事實上,*總是*贊成組合繼承! – 2010-11-13 08:57:39