Skip to content
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

Interceptors and inheritance #11

Open
mraleph opened this issue Mar 31, 2015 · 1 comment
Open

Interceptors and inheritance #11

mraleph opened this issue Mar 31, 2015 · 1 comment
Labels

Comments

@mraleph
Copy link

mraleph commented Mar 31, 2015

Imagine that I have a class with an intercepted field:

class X {
  @interceptor var field;
}

what happens if I extend it and overload intercepted field:

class Y extends X {
  var _field;
  get field => _field;
  set field(value) { _field = value; }
}

as it is specified right now interceptor stops working, it will not intercept access to the field in Y. Should be make interceptors contagious, e.g. they are always pushed down to bottom most overriding implementation? Seems like the best choice to me.

(This would slightly complicate semantics of the super invocation that would have to skip interception to avoid executing interceptor twice).

We can also make it configurable and let interceptor implementor choose.

Similarly what happens if Y implements X?

Should interceptor be part of the interface, e.g. should it be "inherited" as well? This is espeically important for interceptors that are "type like", e.g. @notnull because these type like interceptors are obvious part of the interface and not of the implementation.

Related question, how do I intercept method below:

library xyz;

class PublicInterface {
  factory PublicInterface() => new _PrivateImplementation();

  method();
}

class _PrivateImplementation implements PublicInterface {
  method() { /* ... */ };
}
@sigmundch
Copy link
Owner

(This would slightly complicate semantics of the super invocation that would have to skip interception to avoid executing interceptor twice).

I'm not sure we actually need to skip the interception a second time. Afterall, we are intercepting 2 members (they just happen to shadow each other).

Should interceptor be part of the interface, ... ?

Great question! It seems that several design choices boil down to this (whether interceptors are part of the API or they are just an implementation detail).

If they are an implementation detail, then, I'd say it shouldn't be contagious.

If they are part of the API, one option is to make it contagious as you describe. Another option is to make it an error if you don't specify the interceptor in the child member as well (similar to how we make it an error if you change the number of arguments in method overrides). If we make it an overriding error, the annotation based syntax might be counter-intuitive to users, so I would consider a separate syntax in that case.

We can also make it configurable and let interceptor implementor choose.

That's an interesting idea. I do wonder how much this is a choice of the interceptor, or a choice done when decorating members with an interceptor

Related question, how do I intercept method below...

That's an interesting scenario. If you are annotating the members from the side (e.g. with @ApplyIncerceptorTo), then I can see how making it contagious would address this issue, the other option is to make this side annotation more powerful:

@ApplyInterceptorTo(PublicInterface, #method, includeImplementations: true)
import 'xyz.dart';

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants