This is an old revision of the document!
PHP RFC: Interface Default Methods
- Version: 1.0
- Date: 2022-06-27
- Author: Levi Morrison, levim@php.net
- Status: Under Discussion
- First Published at: http://wiki.php.net/rfc/interface-default-methods
Introduction
Over time, authors sometimes want to add methods to an interface. Today, this causes large breakages to every implementor. This RFC proposes a way to reduce the scale of breakage.
Additionally, some times interfaces can implement some functionality of their interface in terms of other parts. For example, the interface Countable
could implement function isEmpty(): bool
by using $this->count() == 0
. Today, traits are often used to accomplish this, but default interface implementation could be used instead.
Proposal
Interface methods can now provide a default implementation.
interface Example { // Today, you cannot specify an implementation, only a // signature. function method1(): void; // With this RFC, you can provide an implementation: function method2(): void { echo __METHOD__, "\n"; } }
Default Method Resolution
Default methods for interfaces introduce a form of multiple inheritance. How is a method selected?
Java's resolution algorithm looks like this:
- Class definitions always win. If a class, or a parent class, defines a concrete method, then this will always win over all possible default methods.
- More specific interfaces take priority over less specific ones. If interfaces
A
andB
exist andB
extendsA
, and both have a default method for the same method, then when a class implements B directly or indirectly the method fromB
will take precedence over the method fromA
. - If the above rules fail, then the class needs to implement the method itself, possibly delegating to one of the interfaces.
This RFC proposes the same. However, rule 2 has not yet been implemented so I am unsure how feasible it is.
Here's an example of a class delegating to another method:
interface Interface1 { function method1() { echo __METHOD__ . "\n"; } } interface Interface2 { function method1() { echo __METHOD__ . "\n"; } } class Class1 implements Interface1, Interface2 { function method1() { Interface1::method1(); } } (new Class1())->method1(); // Interface1::method1
Backward Incompatible Changes
None, as long as you do not use the feature.
If you do use the feature:
- Adding a default implementation to an existing interface method will not break existing code, because every existing usage has a higher priority than the default.
- If you add a new method to an interface, there is a compatibility break. The impact of the break is limited to places where the implementor/inheritor of the interface has a method of the same name.
Proposed PHP Version(s)
PHP 8.NEXT.
RFC Impact
To Existing Extensions
Modules can specify an interface implementation as well.
To Opcache
Opcache should also work with this feature.
To the Ecosystem
Previously, interface methods were not allowed to have method bodies. These tools such as parsers, code analyzers, etc will need to be updated.
Open Issues
Make sure there are no open issues when the vote starts!
Future Scope
This feature may be used to enhance existing interfaces in PHP.
Countable
could addfunction isEmpty(): bool { return $this->count() == 0; }
.Iterator
could add methods likemap
,filter
, andreduce
which behave similarly toarray_map
,array_filter
, andarray_reduce
.
Voting
The vote will be a simple yes/no vote on whether to include the feature.
Patches and Tests
Here is a work-in-progress pull request: https://github.com/php/php-src/pull/11467.
Implementation
After the project is implemented, this section should contain
- the version(s) it was merged into
- a link to the git commit(s)
- a link to the PHP manual entry for the feature
- a link to the language specification section (if any)
References
Links to external references, discussions or RFCs
Rejected Features
Keep this updated with features that were discussed on the mail lists.