2012-11-13 17 views
11

Widziałem termin "Expando" używany ostatnio w Dart. Brzmi interesująco. API nie dawało mi wiele wskazówki.Co to jest funkcja "Expando" w Dart, co robi?

Przykład lub dwa mogą być najbardziej pomocne!

(Nie jestem pewien, czy jest to powiązane, ale najbardziej zależy mi na sposobie dodawania metod (modułów pobierających) i/lub zmiennych do klasy.) Mając nadzieję, że to może być klucz do rozwiązania tego problemu. (Wskazówka: jestem stosując metodę Nosuchmethod teraz i chcą być w stanie powrócić wartość metody unfound.))

Dzięki z góry,

_swarmii

Odpowiedz

10

Expandos pozwalają skojarzyć obiektów do innych obiektów. Jednym z bardzo przydatnych przykładów jest element HTML DOM, który sam nie może być podklasowany. Zróbmy expando najwyższego poziomu, aby dodać niektóre funkcje do elementu - w tym przypadku podpis funkcji podanej w rachunku typedef:

typedef CustomFunction(int foo, String bar); 

Expando<CustomFunction> domFunctionExpando = new Expando<CustomFunction>(); 

teraz z niego korzystać:

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'); 
} 
+7

Czym różni się ten element od mapy ? –

1

Grałem z nim trochę. Oto co mam.

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

W dniu, w którym to publikuję, wersja Dart jest r19425 –

4

Wystarczy, aby wyjaśnić różnicę między EXPANDO i map: jak podano w groups, EXPANDO ma słabe referencje.
Oznacza to, że klucz można wyrzucić, nawet jeśli nadal jest obecny w expando (o ile nie ma innych odniesień do niego).

Dla wszystkich innych celów i celów jest to mapa.