在Dart中,如何在所有类函数之前执行一个函数?

r55awzrz  于 2023-03-10  发布在  其他
关注(0)|答案(2)|浏览(112)

我需要在类的每个函数之前运行一个特定的函数。(在构造函数中不是一次)。它基本上需要在函数内部发生,但在开始时。
我也不想这么做:

class A {
  shouldRunFirstFunction() {}

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

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

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

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

我认为在其他语言中,你可以从类B扩展,然后做一些事情,这样某个函数在类A的函数之前执行。

92dk7w1h

92dk7w1h1#

听起来你需要两个(或更多)类,一种策略是把你的实现放在一个类中,把管理放在另一个类中:

class AImpl {
  shouldRunFirstFunction() {}

  functionA() {
    ...
  }

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

用途:

a.getInstance().functionA(();

我不知道您的确切用例,因此可能是完全不同的东西,但是将控件与实现分离可能是您想要的。

cbwuti44

cbwuti442#

没有什么好的方法可以做到这一点,正确的做法是创建一个实现基接口的转发类:

class ForwardingA implements A {
  A a;

  ForwardingA(this.a);

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

  ...
}

这样,您就可以确保覆盖A的所有成员(如果不这样做,将出现编译时错误)。
你也许可以实现一些代码生成的解决方案,给定一个类A,为你生成ForwardingA,然而,这可能会是更多的工作,特别是当你在少数情况下这样做。
另一种方法是使noSuchMethod半自动地将方法调用转发给委托:

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();
}

其打印:

Hello world!
A
Hello world!
B

但是,我不建议这样做,因为:

  • noSuchMethod将导致运行时性能损失。
  • 它不是完全自动的,你需要手动构建Symbol-to-FunctionMap,更糟糕的是,如果你不小心遗漏了A的一个成员,或者在它的一个Symbol上打错了字,就没有编译时保护。

相关问题