2014-01-16 83 views
0

我有一些抽象類MyClassfoo方法。當有人從這個類繼承並重寫此方法時,從子類調用此方法是非常重要的。所以我想在這種情況發生的時候發出警告。但我不能修改兒童班,因爲它不是我設計的。另外foo方法可以被覆蓋但不必。重寫方法時顯示警告

在代碼中,調用FirstClass::foo()應該會引起警告,但不是SecondClass::foo()。我怎樣才能做到這一點?

abstract class MyClass { 
    public function foo() { 
     // do something important 
    } 
} 

class FirstClass extends MyClass { 
    public function foo() { 
     // do something special 
    } 
} 

class SecondClass extends MyClass { 
    public function foo() { 
     parent::foo(); 
     // do something special 
    } 
} 
+0

請顯示警告消息,因爲您目前的代碼是正確的。 –

+1

這不是一種反模式,因此父方法需要被覆蓋嗎? http://en.wikipedia.org/wiki/Call_super – Flosculus

+0

常識 - 沒有。因爲你無法從外部範圍預測內部方法發生了什麼。如果它是_you_誰正在設計你的孩子班 - 那麼爲什麼不直接添加直接檢查?如果不是你 - 那麼你應該添加一些問題 –

回答

0

你不能這樣做。你可以給你的抽象類添加一些標誌並檢查它,但這是錯誤的。

我建議你改用Template method pattern

abstract class MyClass { 
    final public function foo() { 
     // do something important 
     $this->_overridableMethod(); 
    } 

    abstract protected function _overridableMethod(); 
} 

class FirstClass extends MyClass { 
    protected function _overridableMethod(){ 
     // do something special 
    } 
} 
+0

這可以在不使用'final'的情況下完成嗎?我們有些人遵循一切應該可擴展的哲學。 – Flosculus

+0

@Flosculus,哲學:編寫沒有警告的代碼? – sectus

+0

這是一個很好的解決方案。我沒有想過這種設計模式。但是現在,子類必須實現'_overridableMethod()'。在我的情況下,有人不必實現_foo_方法,但如果他想要它可以。 – user3106462

0

這裏是我會怎麼做這個骨架例如:

interface VehicleInterface 
{ 
    public function move($x, $y); 

    public function refuel($station); 
} 

interface FlyableInterface 
{ 
    public function takeoff(); 

    public function land(); 
} 

abstract class AbstractVehicle implements VehicleInterface 
{ 
    /** 
    * Implementation to refuel at station 
    */ 
    public function refuel($station) 
    { 

    } 
} 

class Car extends AbstractVehicle 
{ 
    /** 
    * Implementation to move by following a road. 
    */ 
    public function move($x, $y) 
    { 

    } 
} 

class Plane extends AbstractVehicle implements FlyableInterface 
{ 
    /** 
    * Implementation to move by means of flying. 
    */ 
    public function move($x, $y) 
    { 

    } 

    /** 
    * Override of AbstractVehicle::refuel, landing required first. 
    */ 
    public function refuel($station) 
    { 
     $this->land(); 
     parent::refuel($station); 
    } 

    /** 
    * Implementation for plane to take off. 
    */ 
    public function takeoff() 
    { 

    } 

    /** 
    * Implementation to land the plane. 
    */ 
    public function land() 
    { 

    } 
} 

$vehicles = array(new Car(), new Plane()); 

$x = '145'; 
$y = '751'; 

foreach($vehicles as $vehicle) { 

    if($vehicle instanceof FlyableInterface) { 
     $vehicle->takeoff(); 
     $vehicle->move($x, $y); 
     $vehicle->land(); 
    } else { 
     $vehicle->move($x, $y); 
    } 
} 

末的執行腳本打算執行相同的任務每輛車的不同取決於方法爲每個類實現。飛機和汽車都採用相同的方法,它們都繼承了相同的方法,但飛機必須首先降落。

正在執行的腳本會通過檢查它是否是特定接口的實例來檢測支持哪些方法。

例如,在實踐中,Symfony2類Command有一個變體,稱爲ContainerAwareCommand。通過擴展它,框架知道注入服務容器,因爲支持的方法是由子類繼承或實現的。