0

Say I have a package that exposes a mixin that provides some extensibility through an API:

mixin ListenerModifier<T> {
  T get value;
  void addListener(Callback callback);
  void removeListener(Callback callback);
}

Say I want to make a "plugin" based on this mixin:

mixin PreviousValue<T> on ListenerModifier<T> {
  late T previous;

  const PreviousValue() {
    addListener(() => previous = value);
  }
}

(You could also have plugins defined in other packages as well, perhaps to expose a Stream<T> getter.)

Then, a user could use any plugins at will, like this:

abstract class MyListener<T> with ListenerModifier<T>, PreviousValue<T> {}

The issue is, mixins can't have constructors like the above PreviousValue assumes. Is there some OOP/architectural way to get around this problem? I initially thought of just forcing users of PreviousValue (for example) to call a registerPreviousValue() method in their MyListener constructor as a workaround, but that is highly error prone.

Related:

Gregory Conrad
  • 1,324
  • 11
  • 19

1 Answers1

0

Just realized for the particular example I gave, I can use a different sort of plugin system without mixins:

mixin ListenerModifierPluginAPI {
  T get value;
  void addListener(Callback callback);
  void removeListener(Callback callback);
}

abstract class ListenerModifier with ListenerModifierPluginAPI {
  T registerPlugin<T>(T Function(ListenerModifierPluginAPI) plugin) => plugin(this);
}

class MyListenerModifier extends ListenerModifier {
  late final PreviousValueState previousValueState;

  const MyListenerModifier() {
    previousValueState = registerPlugin(previousValuePlugin);
  }

  // ...
}

This may not work for all people though. If someone has a different solution, I am all ears.

Gregory Conrad
  • 1,324
  • 11
  • 19