Language: Declare extensions methods directly in class.

Created on 16 Mar 2020  路  6Comments  路  Source: dart-lang/language

It's possible to declare a class and an extension on that class in the same library.
Instead of requiring an extra extension, we could allow extension members to be declared directly in the class itself.
Example:

class Point<T extends num> {
  T x;
  T y;
  Point(this.x, this.y);
  extension double get distanceFromOrigo => sqrt(x * x + y * y);
}

This will introduce a distanceFromOrigo extension on the Point<T extends num> type, just as if you had written

extension PointExtension<T> on Point<T> {
  double get distanceFromOrigo => sqrt(x * x + y * y);
}

Unlike named extensions, this particular extension cannot be disabled by not importing Point.
It's an inherent extension of the Point class, so it can always be used on something of type Point, even if the library doesn't directly import Point. (Because the extension is declared by the same author as the class it's on, it gets preferential treatment wrt. that type).
It can still be shadowed by more specific extensions or by subclass instance members.

Such inherent extension methods can be used as simple interface default methods. It's not a fully fletched default method feature because the methods are not virtual (proper interface default methods are).

Alternatively, we should just introduce interface default methods (#884). They would cover the same use-cases and would also be virtual.

feature

All 6 comments

As you mention, interface default methods would be more powerful: A class C could have an implementation of foo from an interface default method declaration in something that it implements, and a subclass D extends C could override that. And we would get the relevant implementation in both statically checked and dynamic invocations.

So there would need to be a really good reason for having the "in-class extension methods", thus complicating the language (because we have both) or preventing interface default methods from being added. Do in-class extension methods have a killer benefit?

I think I didn't get the point...

What can a "default interface method" do that a mixin can't?
For me it makes sense in languages like C# (default methods on interfaces available on C# 8), as they don't have mixins nor traits... But I don't really see the benefit on Dart.

Could you please enlighten me on this topic?

Extensions are named.

They can have a visibility different from the class they add functionality to.

@mateusfccp wrote:

What can a "default interface method" do that a mixin can't?

You need to take action explicitly in order to obtain an implementation of a member which is declared in a mixin M (typically: add with M to a class declaration). But with an interface default method it will be implicit and automatic.

Concretely, the mixin based approach will not help you if a new method foo is added to an existing class C which is being implemented by a large number of classes D1 .. Dk: You'll have to edit each of the Dj in order to get an implementation of foo. But if you can write foo as an interface default method in C with an implementation, then foo both be in the interface of each Dj and the implementation in C will be used. Of course, if some Dj already implements a foo member which is incompatible with the new method C.foo then you still have some breakage, but that's not very likely to happen. Subclasses of C will of course get the implementation as well. So this means that it is less breaking to add a new member to a class.

Extension methods are also not likely to break subtypes (because they will be used by any receiver type which is a subtype of the on type of the extension), but they can't be virtual.

This seems like a funny way to introduce non-virtual methods. Why not just have non-virtual methods?

Non-virtual methods are interesting.

Then, I really like the entire C# object model with new/override distinction. Being non-virtual is not the goal, being able to add a member with the same name in a subclass without conflicting is. But that's another feature request 馃榿

I do occasionally see classes and extensions on those classes declared next to each other, but I guess that in most of those cases, the extension is either not on the entire class (for example only on Foo<int> rather than Foo<T>), or it's on something which isn't a class (like an enum, we really should allow methods on enums).

Was this page helpful?
0 / 5 - 0 ratings

Related issues

har79 picture har79  路  5Comments

listepo picture listepo  路  3Comments

dev-aentgs picture dev-aentgs  路  3Comments

wytesk133 picture wytesk133  路  4Comments

stategen picture stategen  路  4Comments