Skip to content
Advertisement

Can I implement an interface and override the return type of one of the interface’s methods?

I have a Task class that extends an abstract class, TaskBase.

JavaScript

This TaskBase implements an interface CommanTask, which contains the following method.

JavaScript

Now I need a new task class TaskMultiple, and it’s process() method needs to return an array of ProcessResult instead of one ProcessResult.

How can I extend abstract class TaskBase for this new TaskMultiple class?

Advertisement

Answer

If you implement an interface, you need to actually comply with the contract laid out by the interface.

The interface you propose says that process() returns a ProcessResult. If you could change that in an implementing class to returning an array, then consumers of the class wouldn’t be able to trust the contract specified by the interface.

They would try to use the result of TaskMultiple::process(), and since they interface says it would return a ProcessResult, a fatal error would soon happen when it tried to treat it as such (e.g. by accessing a method for that class), and it wasn’t that.

Your solutions are:

If you are on PHP 8, you could use union types:

JavaScript

It would work, but it’s ugly. Now consumers of the any Task implementing service would need to check on the result of process() to see if it’s a single ProcessResult, or a collection (presumably of ProcessResults).

If you are on PHP < 8, you could make it work simply by removing the type hint:

JavaScript

Now consumers would only know that there is a process() method, but you’d have no type information at all. Uglier still.

Better, simply create different interfaces like Task and MultipleTask:

JavaScript

Since your BaseTask includes nothing to help implement the class (only includes an abstract method, making it already very similar to an interface), move the implements to each of the concrete task classes:

JavaScript
User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement