dart-lang / dart-lang/language
Interface default methods
- Dominant language
- TeX
- Stars
- 2.9k
- Forks
- 239
- Avg merge
- 2d 18h
- Merged PRs (30d)
- 14
Description
See more detailed proposal here: https://github.com/dart-lang/language/blob/master/working/0884/interface_default_methods_proposal.md
Adding new members to an interface is a breaking change in Dart, for several reasons.
One reason is that a subclass might already implement the interface, and it won't have an implementation of the new member, and that's a compile-time error.
(Other reasons include subclasses already having a member with that name and an incompatible interface).
An *interface default method* is a concrete method added to an *interface* which is inherited (or rather: mixed in) by all non-abstract classes *implementing* the interface. It's implementation inheritance along implements relations.
As such, it needs to be controlled in order to avoid the issues that caused the user to use `implements` over `extends`.
Not all methods will be inherited, so an interface default method needs to be marked as such, perhaps with the `default` keyword:
```dart
default double get distanceFromOrigo => sqrt(x * x + y * y);
```
The method is not just inherited along the normal superclass path. Instead it is *mixed in* on any class which implements the interface where the default method was introduced, and which does not already declare or inherit a non-synthetic concrete member with the same name.
This uses the existing member mix-in functionality which is used to mix-in mixin members into mixin application classes, only just for the individual default methods. (We may need to define what mixing in a single member means, but it's completely consistent with what a mixin application does to all the mixin members.)
A synthetic member is either a `noSuchMethod` forwarder *or another default method*. If a class has a non-trivial `noSuchMethod` and an applicable default method, the default method is used. (We might need to reconsider that if it breaks mocks).
A default method must be usable as a mixin member declaration with no super-class requirement, so the default method cannot do super-invocations on anything except `Object` members.
It is a compile-time error if this mixed-in implementation does not satisfy the interface of the class. (Can happen if also implementing another interface with a more specific signature and no default method).
(Effectively: If a class has an interface member with no non-synthetic implementation, if precisely one interface default method applies, mix that in. Otherwise, if the class has a non-trivial `noSuchMethod`, add a nSM-forwarder. Otherwise do nothing, which might cause an error.)
If multiple interfaces can introduce default members with the same name, none of them are mixed in, unless precisely one of the interfaces is a subtype of all the remaining ones. In that case, that interface's default member wins. (Do we need to lower the precedence of platform library default members?)
Compared to extension members, interface default methods are normal, virtual, interface members. All you get is an implicit mixin of number of methods *if you need it*. You can always declare your own implementation of the member, and use normal virtual dispatch to get the best available implementation.
Contributor guide
Research direction
Start by reading working/0884/interface_default_methods_proposal.md, which contains the detailed proposal and unresolved design questions. Done would require an agreed language specification for interface default methods, including inheritance, synthetic members, conflicts, and compile-time errors; the issue does not name implementation files or tests.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- dart
- Domain
- compilers
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100