rfc:interface-default-methods
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
rfc:interface-default-methods [2023/06/15 03:44] – Moving from draft to under discussion levim | rfc:interface-default-methods [2023/07/17 15:06] (current) – Status: declined levim | ||
---|---|---|---|
Line 1: | Line 1: | ||
====== PHP RFC: Interface Default Methods ====== | ====== PHP RFC: Interface Default Methods ====== | ||
- | * Version: | + | * Version: |
* Date: 2022-06-27 | * Date: 2022-06-27 | ||
* Author: Levi Morrison, levim@php.net | * Author: Levi Morrison, levim@php.net | ||
- | * Status: | + | * Status: |
* First Published at: http:// | * First Published at: http:// | ||
Line 10: | Line 10: | ||
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. | 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, | + | Additionally, |
+ | |||
+ | For example, see [[https:// | ||
===== Proposal ===== | ===== Proposal ===== | ||
- | Interface methods can now provide a default | + | Interface methods can now provide a method body. This implementation |
<PHP> | <PHP> | ||
Line 28: | Line 30: | ||
} | } | ||
</ | </ | ||
+ | |||
+ | Interface methods can also now be < | ||
+ | |||
+ | The methods with default implementations are inherited similarly to abstract base classes, as opposed to how traits behave. For instance, a private method on the interface is not accessible to the class which implements the interface; with a trait it would be. | ||
==== Default Method Resolution ==== | ==== Default Method Resolution ==== | ||
Line 38: | Line 44: | ||
- If the above rules fail, then the class needs to implement the method itself, possibly delegating to one of the interfaces. | - 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. | + | This RFC proposes the same. However, rule 2 is only partially implemented at this time. |
Here's an example of a class delegating to another method: | Here's an example of a class delegating to another method: | ||
Line 59: | Line 65: | ||
(new Class1())-> | (new Class1())-> | ||
</ | </ | ||
+ | |||
+ | ==== Parent Scoping ==== | ||
+ | In interface default methods, you cannot use the < | ||
+ | |||
+ | <PHP> | ||
+ | interface Interface1 { | ||
+ | function method1() { echo __METHOD__, PHP_EOL; } | ||
+ | } | ||
+ | |||
+ | interface Interface2 extends Interface1 { | ||
+ | function method1() { parent:: | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | The reason is that interfaces can extend multiple other interfaces e.g. | ||
+ | |||
+ | <PHP> | ||
+ | interface Interface3 extends Interface1, Interface2 {} | ||
+ | </ | ||
+ | |||
+ | The name of the interface should be used instead: | ||
+ | |||
+ | <PHP> | ||
+ | interface Interface2 extends Interface1 { | ||
+ | function method1() { Interface1:: | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | However, if a sub-class of the inheriting class calls '' | ||
+ | |||
+ | <PHP> | ||
+ | interface Interface1 { | ||
+ | function method1() { echo __METHOD__, PHP_EOL; } | ||
+ | } | ||
+ | |||
+ | class Class1 implements Interface1 { | ||
+ | // Inherits Interface1:: | ||
+ | } | ||
+ | |||
+ | class Class2 extends Class1 { | ||
+ | function method1() { parent:: | ||
+ | } | ||
+ | |||
+ | (new Class2())-> | ||
+ | // output: | ||
+ | // Interface1:: | ||
+ | </ | ||
+ | |||
+ | ==== Cancelling Default Methods ==== | ||
+ | If an interface method extends a parent interface method which has a default, this prevents using the default method for classes which implement the child interface but do not directly implement the parent one: | ||
+ | |||
+ | <PHP> | ||
+ | interface Interface1 { | ||
+ | function method1() { echo __METHOD__, " | ||
+ | } | ||
+ | |||
+ | interface Interface2 extends Interface1 { | ||
+ | function method1(); | ||
+ | } | ||
+ | |||
+ | /* Would be an error because method1 has not been implemented. | ||
+ | class Class1 implements Interface2 { | ||
+ | // error: method1 has not been implemented. | ||
+ | } | ||
+ | */ | ||
+ | |||
+ | // This is subtly different, but valid: | ||
+ | class Class1 implements Interface1, Interface2 {} | ||
+ | </ | ||
+ | |||
+ | The behavior could go either way. I picked this behavior because if it's wrong, it's easier to correct than the other way around. | ||
===== Backward Incompatible Changes ===== | ===== Backward Incompatible Changes ===== | ||
Line 68: | Line 145: | ||
===== Proposed PHP Version(s) ===== | ===== Proposed PHP Version(s) ===== | ||
- | PHP 8.NEXT. | + | PHP 8.3. |
===== RFC Impact ===== | ===== RFC Impact ===== | ||
- | ==== To Existing | + | ==== To Extensions ==== |
- | Modules can specify an interface implementation as well. | + | Modules can specify an interface implementation as well. These internal default methods should not be marked with '' |
==== To Opcache ==== | ==== To Opcache ==== | ||
- | Opcache should also work with this feature. | + | Opcache should also work with this feature. The proof of concept implementation has not triggered any issues so far in CI. |
+ | |||
+ | ==== 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 ===== | ===== Open Issues ===== | ||
Line 89: | Line 169: | ||
===== Voting ===== | ===== Voting ===== | ||
The vote will be a simple yes/no vote on whether to include the feature. | The vote will be a simple yes/no vote on whether to include the feature. | ||
+ | <doodle title=" | ||
+ | * Yes | ||
+ | * No | ||
+ | </ | ||
+ | |||
===== Patches and Tests ===== | ===== Patches and Tests ===== | ||
- | WIP: https:// | + | Here is a work-in-progress pull request: https:// |
===== Implementation ===== | ===== Implementation ===== |
rfc/interface-default-methods.1686800640.txt.gz · Last modified: 2023/06/15 03:44 by levim