What is the Dart “Expando” feature about, what does it do?

后端 未结 3 952
灰色年华
灰色年华 2020-12-30 00:23

Have been seeing the term \"Expando\" used recently with Dart. Sounds interesting. The API did not provide much of a clue to me.

An example or two could be most he

相关标签:
3条回答
  • 2020-12-30 00:53

    I played with it a little bit. Here's what I've got.

    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>);
    }
    
    0 讨论(0)
  • 2020-12-30 00:56

    Just to clarify the difference between expando and maps: as reported in the groups, expando has weak references.
    This means that a key can be garbage collected even if it's still present in the expando (as long as there are no other references to it).

    For all other intents and purposes it's a map.

    0 讨论(0)
  • 2020-12-30 01:05

    Expandos allow you to associate objects to other objects. One very useful example of this is an HTML DOM element, which cannot itself be sub-classed. Let's make a top-level expando to add some functionality to an element - in this case a Function signature given in the typedef statement:

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

    Now to use it:

    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');
    }
    
    0 讨论(0)
提交回复
热议问题