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.
ho notato che il vostro link non funzionavano, così li ho aggiornati. –
Nizza, grazie Andrew;) –