Skip to content

Inherent extensions #3220

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
ds84182 opened this issue Jul 17, 2023 · 3 comments
Open

Inherent extensions #3220

ds84182 opened this issue Jul 17, 2023 · 3 comments
Labels
feature Proposed language feature that solves one or more problems

Comments

@ds84182
Copy link

ds84182 commented Jul 17, 2023

When designing an API that includes usage of private fields that are exposed publicly in some form, it is generally undesirable to allow polymorphism on some members. Take the following example:

// Assume we're using some new nifty features for brevity purposes.
abstract base class Node<
  N extends Self,
  P extends Node<_, _, N>,
  C extends Node<N, _, _>
> {
  P? _parent;
  C? _firstChild;
  C? _lastChild;
  N? _previous;
  N? _next;

  Node.detached();

  void reparent(N parent) {
    // ... this implementation is VERY important
  }
}

A subtype can override reparent! That's not good, something like this should be statically dispatched.

The workaround today is to place it in a separate extension, but that doesn't play well with import '...' show Node;.

I propose that extension methods and bodies be allowed within classes:

abstract base class Node<...> {
  extension void reparent(N parent); // Like an extension on Node<...> but is always visible.
  extension on Node<Some, Specific, Types> {
    // Bodies are supported, with refinement typing. Just no extensions with names.
  }
}

For extension disambiguation, extension members require a cast: (node as Node).reparent(parent)

@ds84182 ds84182 added the feature Proposed language feature that solves one or more problems label Jul 17, 2023
@eernstg
Copy link
Member

eernstg commented Jul 18, 2023

Note similarity to #2510.

@ds84182
Copy link
Author

ds84182 commented Aug 15, 2023

When I originally read that bug I thought it was for default impls that were overridable. The only difference there is the extension bodies for refinement.

@lrhn
Copy link
Member

lrhn commented Aug 15, 2023

I think what you really want here is a final member which cannot be overridden in subclasses extending the type.
(Something like #3141, but simpler.)
If you then also use base to ensure that all subclasses must extend the type, not implement, then the method should be safe from any fiddling.

Using extension members means using the type parameters of the extension, based on the static type the extension is invoked on, not the type variables of the class itself. A non-overridable instance member would not have that problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature Proposed language feature that solves one or more problems
Projects
None yet
Development

No branches or pull requests

3 participants