2014-01-16 5 views
0

У меня есть несколько абстрактных классов MyClass с foo метод. Важно вызвать этот метод из дочернего класса, когда кто-то из этого класса и переопределит эти методы. Поэтому я хочу показать предупреждение, когда эта ситуация случится. Но я не могу изменить дочерний класс, потому что он не разработан мной. Кроме того, 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); 
    } 
} 

Исполнительное сценарий в конце намерен выполнить ту же задачу для каждого транспортного средства по-разному в зависимости от методов, каждый класс реализует. Как самолет, так и автомобиль реализуют один и тот же метод move, и оба они наследуют один и тот же метод refuel, однако самолет должен сначала приземлиться.

Сценарий выполнения определит, какие методы поддерживаются, проверяя, является ли это экземпляром определенного интерфейса.

Для примера на практике класс Symfony2 Command имеет вариант, называемый ContainerAwareCommand. Расширяя это, структура знает, чтобы ввести контейнер обслуживания, потому что поддерживаемые методы для этого либо наследуются, либо реализуются дочерним классом.

Смежные вопросы