Vincent
Vincent

Reputation: 1730

How to force a child class to implement its parent class interface methods

I have multiple child classes that extend a parent class.

I want to "force" the child classes to have a list of methods declared in each one of them.

class childClass_A{
    function interfaceMethod(){}
}
class childClass_B{
    function interfaceMethod(){}
}
etc.

In order to do so, I looked into interfaces.

I understand I can make all the child classes implement a specific interfaces but would not that be redundant code?

class childClass_A implements MyInterface{
    function interfaceMethod(){}
}
class childClass_B implements MyInterface{
    function interfaceMethod(){}
}
etc.

Instead, I thought of making the parent class implement the interface.

class parentClass implements MyInterface{
    function interfaceMethod(){}
}

class childClass_A extends parentClass{

}

However, by doing so, the "obligation" to declare the interface methods is assigned to the parent class, and if the child class does not include one of the interface's method, no error is generated.

Is it possible to ensure the parent object's interface methods are also declared in the child classes?

Upvotes: 6

Views: 2168

Answers (2)

Jared Farrish
Jared Farrish

Reputation: 49198

Given a simple interface (contract):

interface Foo {
    public function test(string $value);
}

How can we implement this so that this given manner of interacting with the implementing class is consistent, yet variable. We can build a simpler type class, then extend it twice:

class Bar implements Foo {
    public function test(string $value) {
        var_dump(__METHOD__, $value);
    }
}

class Baz extends Bar {}

class Bop extends Bar {
    public function test(string $value) {
        var_dump(__METHOD__, $value);
    }
}

There's nothing wrong there, of course, unless you want to force the implementation of the method on the extending class. Think of this as a class partial, then, something that needs the extending class to make itself useful. This is an abstraction of the "base" class, meaning it cannot be constructed without extension itself.

abstract class Fan implements Foo {
    abstract public function test(string $value);

    public function otherTest(string $value) {
        var_dump(__METHOD__, $value);
    }
}

Note we have to declare with abstract on the Foo::test() requirement. This will require the extending class observe the interface contract:

abstract class Fan implements Foo {
    abstract public function test(string $value);

    public function otherTest(string $value) {
        var_dump(__METHOD__, $value);
    }
}

class Bop extends Fan {
    public function test(string $value) {
        var_dump(__METHOD__, $value);
    }
}

class Fin extends Fan {
    public function test(string $value) {
        var_dump(__METHOD__, $value);
    }
}

https://3v4l.org/aMLGv

Also note that a Trait might be preferred, if you're grouping around methodology and want to be able to share. Traits also satisfy interfaces, and apply as private in scope.

trait Test {
    public function test(string $value) {
        var_dump(__METHOD__, $value);
    }
}

class Bop implements Foo {
    use Test;
}

class Fin implements Foo {
    use Test;
}

Upvotes: 2

Matthew Daly
Matthew Daly

Reputation: 9476

You can declare the parent class as abstract, and declare the required methods as abstract too.

That way, the child classes must implement those methods, just as with an interface, otherwise they cannot be instantiated.

If you needed to reuse one or more methods for specific child classes, you could consider defining them in a trait.

Upvotes: 7

Related Questions