【问题标题】:What is the Dart "Expando" feature about, what does it do?Dart 的“Expando”功能是什么,它有什么作用?
【发布时间】:2012-11-01 17:18:20
【问题描述】:

最近在 Dart 中使用了“Expando”一词。听起来不错。 API 没有为我提供太多线索。

一两个例子可能最有帮助!

(不确定这是否相关,但我最渴望向类添加方法(getter)和/或变量的方法。希望这可能是解决这个问题的关键。(提示:我正在使用Nosuchmethod 方法现在并希望能够返回未找到方法的值。))

提前致谢,

_swarmii

【问题讨论】:

    标签: dart expando nosuchmethod


    【解决方案1】:

    Expandos 允许您将对象与其他对象相关联。一个非常有用的例子是 HTML DOM 元素,它本身不能被子类化。让我们做一个顶级扩展来为元素添加一些功能 - 在这种情况下,typedef 语句中给出了 Function 签名:

    typedef CustomFunction(int foo, String bar);
    
    Expando<CustomFunction> domFunctionExpando = new Expando<CustomFunction>();
    

    现在使用它:

    main(){
       // Assumes dart:html is imported
       final myElement = new DivElement();
    
       // Use the expando on our DOM element.
       domFunctionExpando[myElement] = someFunc;
    
       // Now that we've "attached" the function to our object,
       // we can call it like so:
       domFunctionExpando[myElement](42, 'expandos are cool');
    }
    
    void someFunc(int foo, String bar){
      print('Hello. $foo $bar');
    }
    

    【讨论】:

    • 这和 Map 有什么不同?
    • @ZdeněkMlčoch Expando 不会阻止密钥的垃圾收集!在这方面,它可以与 JavaScript 的 WeakMap 相提并论。
    【解决方案2】:

    只是为了澄清 expando 和地图之间的区别:正如 groups 中所报告的,expando 有弱引用
    这意味着即使键仍然存在于 expando 中(只要没有其他对它的引用),它也可以被垃圾回收。

    对于所有其他意图和目的,它是一张地图。

    【讨论】:

      【解决方案3】:

      我玩了一下。这就是我所拥有的。

      import 'dart:html';
      
      const String cHidden = 'hidden';
      
      class ExpandoElement {
        static final Expando<ExpandoElement> expando =
            new Expando<ExpandoElement>("ExpandoElement.expando");
      
        final Element element;
      
        const ExpandoElement._expand(this.element);
      
        static Element expand(Element element) {
          if (expando[element] == null)
            expando[element] = new ExpandoElement._expand(element);
          return element;
        }
      
      //  bool get hidden => element.hidden; // commented out to test noSuchMethod()
        void set hidden(bool hidden) {
          if (element.hidden = hidden)
            element.classes.add(cHidden);
          else
            element.classes.remove(cHidden);
        }
      
        noSuchMethod(InvocationMirror invocation) => invocation.invokeOn(element);
      }
      final Expando<ExpandoElement> x = ExpandoElement.expando;
      Element xquery(String selector) => ExpandoElement.expand(query(selector));
      
      final Element input = xquery('#input');
      
      void main() {
        input.classes.remove(cHidden);
        assert(!input.classes.contains(cHidden));
      
        input.hidden = true;
        assert(x[input].hidden); // Dart Editor warning here, but it's still true
        assert(!input.classes.contains(cHidden)); // no effect
      
        input.hidden = false;
        assert(!x[input].hidden); // same warning, but we'll get input.hidden via noSuchMethod()
        assert(!input.classes.contains(cHidden));
      
        x[input].hidden = true;
        assert(input.hidden); // set by the setter of ExpandoElement.hidden
        assert(input.classes.contains(cHidden)); // added by the setter
        assert(x[input].hidden);
        assert(x[input].classes.contains(cHidden)); // this is input.classes
      
        x[input].hidden = false;
        assert(!input.hidden); // set by the setter
        assert(!input.classes.contains(cHidden)); // removed by the setter
        assert(!x[input].hidden);
        assert(!x[input].classes.contains(cHidden));
      
        // confused?
        assert(input is Element);
        assert(x[input] is! Element); // is not
        assert(x[input] is ExpandoElement);
        assert(x is Expando<ExpandoElement>);
      }
      

      【讨论】:

      • 在我发布这个的那天,Dart 版本是 r19425
      猜你喜欢
      • 2011-01-14
      • 1970-01-01
      • 2019-04-26
      • 2016-04-29
      • 2017-03-02
      • 2012-10-04
      • 1970-01-01
      • 2020-09-11
      • 2011-04-01
      相关资源
      最近更新 更多