2010-04-05 5 views
5

Sto cercando idee su come implementare un sistema stile Mixin/Trait in AS3.Implementazione di missaggio o tratto in AS3?

Voglio essere in grado di comporre un numero di classi insieme in un singolo oggetto. Naturalmente questa non è una funzionalità a livello di linguaggio di AS3, ma spero che ci sia forse un modo per farlo usando tecniche basate su prototipi o forse qualche hacking bytecode che credo utilizzi AsMock per implementare la sua funzionalità.

Un esempio Java esistente è Qi4J dove l'utente definisce le interfacce implementate dal framework Qi4j in base ai tag e alla codifica dei metadati per convenzione.

Qualcuno ha qualche idea su come far funzionare il concetto Mixin/Trait all'interno di AS3?

risposta

7

Zero soluzioni presentate su questo, quindi ho esaminato alcuni metodi. Esistono ECMA script style mixins aggiungendo metodi definiti su altri oggetti al prototipo degli oggetti di base. Ma questo significa che i vantaggi della digitazione statica sono andati.

Stavo cercando una soluzione che non ha scavalcato il sistema di tipo statico. Sapevo che ASMock usato da bytecode injection per creare classi proxy. Ho hackerato lo ASMock per gli ultimi giorni e ho trovato una possibile soluzione implementata creando una classe con classi composte (attraverso l'iniezione bytecode).

Dagli utenti punto di vista si tratta di definire l'oggetto che utilizza mixins attraverso molte interfacce:

public interface Person extends RoomObject, Moveable 

public interface RoomObject 
{ 
    function joinRoom(room:Room):void 
    function get room():Room 
} 

public interface Moveable 
{ 
    function moveTo(location:Point):void 
    function get location():Point 
} 

Poi si definiscono le classi per rappresentare queste interfacce:

public class MoveableImpl implements Moveable 
{ 
    private var _location:Point = new Point() 
    public function get location():Point { return _location } 

    public function move(location:Point):void 
    { 
     _location = location.clone() 
    } 
} 

public class RoomObjectImpl implements RoomObject 
{ 
    private var _room:Room 
    public function get room():Room { return _room } 

    public function joinRoom(room:Room):void 
    { 
     _room = room 
    } 
} 

In una situazione normale in cui vuoi comporre le classi che scriverebbe:

public class PersonImpl implements Person 
{ 
    private var _roomObject:RoomObject = new RoomObjectImpl() 

    private var _moveable:Moveable = new MoveableImpl() 

    public function get room():Room { return _roomObject.room } 

    public function joinRoom(room:Room):void { _roomObject.joinRoom(room) } 

    public function get location():Point { return _moveable.location } 

    public function move(location:Point):void { _moveable.move(location) } 
} 

Questo è facilmente scritto usando il codice a causa del suo layout regolare. E questo è esattamente ciò che fa la mia soluzione, iniettando il bytecode equivillante in una nuova classe. Con questo sistema di iniezione bytecode possiamo creare un oggetto Person in questo modo:

public class Main 
{ 
    private var mixinRepo:MixinRepository = new MixinRepository() 

    public function Main() 
    { 
     with(mixinRepo) 
     { 
      defineMixin(RoomObject, RoomObjectImpl) // associate interfaces with concreate classes 
      defineMixin(Moveable, MoveableImpl) 
      defineBase(Person) 
      prepare().completed.add(testMixins) // the injection is a async process, just liek in ASMock 
     } 
    } 

    private function testMixins():void 
    { 
     var person:Person = mixinRepo.create(Person) 
     var room:Room = new Room('room you can play in') 

     person.joinRoom(room) 
     trace('person.room:', person.room) 

     person.move(new Point(1, 2)) 
     trace('person.location:', person.location) 
    } 
} 

Al momento questo sistema è una prova di concetto ed è quindi molto semplice e fragile. Ma mostra che è possibile avvicinarsi a un sistema di stile Scala mix/tratti per AS3. Ho creato un github project per contenere il codice se qualcuno è interessato a eseguire la soluzione e a curiosare su come è stato fatto.

un esempio più completo è dato al progetto wiki.

+0

ho notato che il vostro link non funzionavano, così li ho aggiornati. –

+0

Nizza, grazie Andrew;) –

1

Guarda qui, questo funziona, si mescola in metodi ed è semplice.

http://github.com/specialunderwear/as3-mixin

o, e funziona quando si compila in modalità AS3.

+0

Bella idea, ho deciso di dargli una prova sul mio prossimo progetto AS3. –

+0

Sfortunatamente, farlo in questo modo non aiuta il type-checker :(. –

+0

Poiché i mixin sono classi estranee, che non hanno alcuna influenza sul tipo di classe in cui si stanno mixando i metodi, questa è una caratteristica dei mixin, non di questa particolare implementazione Se vuoi che il tipo della tua classe definisca la sua funzionalità (in modo univoco), non dovresti mai usare i mixin. – specialunderwear