Cero soluciones presentadas en esto, así que busqué algunos métodos. Hay ECMA script style mixins agregando métodos definidos en otros objetos al prototipo de objetos base. Pero esto significa que las ventajas de la tipificación estática ya no existen.
Estaba buscando una solución que no dejara de lado el sistema de tipo estático. Sabía que ASMock utilizaba inyección de código para crear clases de proxy. Hace unos días pirateé alrededor de ASMock y se me ocurrió una posible solución implementada mediante la creación de una clase con clases compuestas (a través de la inyección de código de bytes).
De los usuarios punto de vista se trata de definir el objeto que usa mixins a través de muchas interfaces:
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
}
A continuación, definir clases para representar estas interfaces:
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
}
}
En una situación normal, donde desea componer las clases que escribiría:
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) }
}
Esto se escribe fácilmente usando código debido a su diseño regular. Y eso es exactamente lo que hace mi solución, al inyectar el bytecode equivalente en una nueva clase. Con este sistema de inyección de código de bytes podemos crear un objeto Person, así:
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)
}
}
Por el momento este sistema es una prueba de concepto y por lo tanto es muy básico y quebradizo. Pero muestra que es posible acercarse al sistema de estilo Scala mixin/traits de AS3. He creado un github project para guardar el código si alguien está interesado en ejecutar la solución y echar un vistazo a cómo se hizo.
Un ejemplo más completo se da en el proyecto wiki.
me di cuenta de que sus enlaces no funcionaban, así que les he actualizado. –
Bien, gracias Andrew;) –