Given an object/interface hierarchy like the following
<?php
interface Event
{
public function getType(): string;
}
final class MyEvent implements Event
{
public function getType(): string
{
return 'MyEvent';
}
}
interface EventHandler
{
public function handle(Event $event): void;
}
final class MyEventHandler implements EventHandler
{
public function handle(MyEvent $event): void
{
// do something with the concrete MyEvent object...
}
}
Is it not possible to type hint the more specific MyEvent
in the method which is implementing the handle
method from the EventHandler
interface?
my ide is marking this as an error
Method 'MyEventHandler::handle()' is not compatible with method 'EventHandler::handle()'.
while i feel like in the name of extensibility, this should be possible...
The signature of the implementing method is different to that of the method in the interface, but at runtime wouldn't a MyEvent
be treated the same as an Event
?
Obviously, if the concrete implementation type hints the Event
interface, there is no problem, and at runtime the method will accept the implementing MyEvent
but then we lose the intent that the concrete MyEventHandler
should handle events of type MyEvent
. There could be very many implementations of the Event
and EventHandler
interfaces, so being able to be as explicit as possible is what we're looking for here, rather than just type hinting the interface in the concrete handle method.
If this isn't possible with interfaces and type hinting, is there another way of implementing this with an abstract class perhaps while retaining the strong(ish) typing and conveying the intent? Or would we need an explicit method in the MyEventHandler
to allow the type hint of the concrete Event class?