简体   繁体   中英

Show warning when overriding method

I have some abstract class MyClass with foo method. It is important to call this method from child class when someone iherits from this class and override this methods. So I want to show warning when this situation will happen. But I can't modify child class, because it isn't designed by me. In addition foo method can be overriden but not have to.

In code, calling FirstClass::foo() should cause warning, but SecondClass::foo() not. How can I do this?

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
    }
}

You cannot do this right. You could add to your abstract class some flag and check it, but it would be wrong.

I propose you to use Template method pattern instead.

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
    }
}

Here is skeleton example of how I would do this:

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);
    }
}

The executing script at the end intends to perform the same task for each vehicle differently depending on the methods each class implements. Both the plane and the car implement the same move method, and they both inherit the the same refuel method, however the plane is required to land first.

The executing script will detect what methods are supported by checking if it is an instance of a particular interface.

For an example in practice, Symfony2 class Command has a variant called ContainerAwareCommand . By extending this, the framework knows to inject the service container because the supported methods to do so are either inherited or implemented by the child class.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM