如何在Dart中实现可事件类型

Dan*_*son 1 events design-patterns dart

是否有内置功能可以在dart中制作可事件类型?

在我的Javascript应用程序中,我使用名为Eventable的类来提供以下功能:

var dog = new Dog() //where Dog inherits from Eventable
var cat = new Cat() //where Cat inherits from Eventable

//use 'on' to listen to events
cat.on(dog, 'bark', cat.runaway); //assuming Cat has a method runaway on its prototype

//use fire to launch events
dog.fire({type: 'bark'});  //this causes cat.runaway(event); to be called
Run Code Online (Sandbox Code Playgroud)

在javascript中一个非常常见的模式,我喜欢它,因为它帮助我保持对象在src和我的脑海中孤立.

使用该on方法创建一个new EventContract具有基于所有者(cat上面),客户端(dog上面),类型('bark'上面)和功能(cat.runaway上面)的唯一密钥.这个唯一键允许我确保不EventContract创建重复的s,但更重要的是它允许我保持EventContract一个对象具有的所有s的易于查找的集合,这样我可以调用:

cat.dispose();
Run Code Online (Sandbox Code Playgroud)

并且所有的事件合同cat都将被销毁,所以我相信所有对cat的外部引用都已被删除,而cat现在可以被GC了.

但是我发现很难在Dart中实现这个功能,因为做类似的事情cat.on(dog, 'bark', cat.runaway);会导致生成一个新函数来封闭(){cat.runaway();},而dart中唯一可以从标准函数对象中获取的唯一键就是它的hashCode,但这意味着我可以回想起cat.on(dog, 'bark', cat.runaway);它会创建一个新的,EventContract因为它创建了另一个独特的闭包而不是处理对原始函数的引用,就像在javascript中一样.

无论如何我在飞镖中实现这种模式?

Zde*_*vic 7

通常,您应该使用Stream惯用的方式在Dart中提供一系列事件.此外,最好在源代码上声明事件(例如,onBark而不是on['bark'].这样的事情应该让你开始:

class Dog {
  var _barkController = new StreamController();
  Stream get onBark => _barkController.stream.asBroadcastStream();
  void bark() => _barkController.add("woof");
}

class Cat {
  void runaway() => print("cat running");
}

void main() {
  var dog = new Dog();
  var cat = new Cat();

  // listen returns subscription object which you can use to unsubscribe
  var sub = dog.onBark.listen((event) => cat.runaway()); 

  dog.bark();  // prints 'cat running'
  sub.cancel();
  dog.bark();  // doesn't print anything
}
Run Code Online (Sandbox Code Playgroud)

如果您希望动态声明事件,可以使用以下内容:

  var sub = dog.on['bark'].listen((event) => cat.runaway()); 
  // in this case `on` is a property of some Events type which overrides
  // operator[] to return appropriate Stream
Run Code Online (Sandbox Code Playgroud)

已有类似的Events类,用于在DOM元素上提供浏览器事件.

此外,还有社区库event_streamevent_source,可以简化此任务.