How can I execute a function before ALL of my class functions in Dart?

177 views Asked by At

I need to run a certain function before every Function of my class. (Not once in a constructor). It basically needs to happen within that function but at the beginning.

I also don't want to do this:

class A {
  shouldRunFirstFunction() {}

  functionA() {
    shouldRunFirst();
    doOtherThings();
  }

  functionB() {
    shouldRunFirst();
    doOtherThings();
  }

  functionC() {
    shouldRunFirst();
    doOtherThings();
  }

  functionD() {
    shouldRunFirst();
    doOtherThings();
  }
}

I think in other languages you can extend from class B and then do something their so a certain function gets executed before a function of class A gets executed.

2

There are 2 answers

2
John Bayko On

It sounds like you want two (or more) classes. One strategy is to put your implementation in one, management in another:

class AImpl {
  shouldRunFirstFunction() {}

  functionA() {
    ...
  }

  ...
}
class A {
  AImpl a;
  getInstance() {
    a.shouldRunFirstFunction();
    return a;
  }
}

To use:

a.getInstance().functionA(();

I don't know your exact use case, so it might be something completely different, but separating the control from the implementation might be what you want.

0
jamesdlin On

There is no good way to do that. The proper thing to do is to create a forwarding class that implements the base interface:

class ForwardingA implements A {
  A a;

  ForwardingA(this.a);

  @override
  void functionA() {
    shouldRunFirstFunction();
    doOtherThings();
  }

  ...
}

And that way you can be sure that you override all of the members of A (if you don't, you will get a compile-time error).

You probably could implement some code-generation solution that, given a class A, generates ForwardingA for you. However, that probably would be way more work, especially if you're doing this for a small number of cases.

Another approach would be to make noSuchMethod forward method calls to a delegate semi-automatically:

class A {
  void functionA() {
    print('A');
  }

  void functionB() {
    print('B');
  }
}

class ForwardingA implements A {
  void Function() preamble;
  A a;

  late final _methods = <Symbol, Function>{
    #functionA: a.functionA,
    #functionB: a.functionB,
  };

  ForwardingA(this.a, this.preamble);

  @override
  dynamic noSuchMethod(Invocation invocation) {
    var f = _methods[invocation.memberName];
    if (f != null) {
      preamble();
      return Function.apply(
        f,
        invocation.positionalArguments,
        invocation.namedArguments,
      );
    }
    
    return super.noSuchMethod(invocation);
  }
}

void main() {
  var foo = ForwardingA(A(), () => print('Hello world!'));
  foo.functionA();
  foo.functionB();
}

which prints:

Hello world!
A
Hello world!
B

However, I would not recommend that since:

  • noSuchMethod will incur a runtime performance penalty.
  • It isn't fully automatic. You need to manually build the Symbol-to-Function Map. Worse, there would be no compile-time protection if you accidentally omit listing one of A's members or make a typo for one of its Symbols.