Внедрение Mixin или Trait в AS3?
Я ищу идеи о том, как реализовать систему стилей Mixin/Trait в AS3.
Я хочу иметь возможность объединить несколько классов в один объект. Конечно, это не особенность языкового уровня AS3, но я надеюсь, что, возможно, есть какой-то способ сделать это, используя методы, основанные на прототипах, или, возможно, некоторый взлом байт-кода, который, как я полагаю, использует AsMock для реализации своей функциональности.
Существующим примером Java является Qi4J, где пользователь определяет интерфейсы, которые реализует инфраструктура Qi4j, на основе тегов метаданных и кодирования в соответствии с соглашением.
У кого-нибудь есть идеи, как заставить работать концепцию Mixin/Trait в AS3?
3 ответа
На этом представлены нулевые решения, поэтому я рассмотрел несколько методов. Существуют миксины стилей сценариев ECMA, добавляющие методы, определенные для других объектов, в прототип базовых объектов. Но это означает, что преимущества статической типизации исчезли.
Я искал решение, которое не обошло бы статическую систему типов. Я знал, что ASMock использовал внедрение байт-кода для создания прокси-классов. Последние несколько дней я взламывал ASMock и придумал возможное решение, реализованное путем создания класса с составными классами (посредством внедрения байт-кода).
С точки зрения пользователей это включает определение вашего объекта, который использует миксины через множество интерфейсов:
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
}
Затем вы определяете классы для представления этих интерфейсов:
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
}
}
В обычной ситуации, когда вы хотите создавать классы, вы должны написать:
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) }
}
Это легко написать с помощью кода из-за его регулярного расположения. И это именно то, что делает мое решение, вводя эквивалентный байт-код в новый класс. С помощью этой системы внедрения байт-кода мы можем создать объект Person следующим образом:
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)
}
}
На данный момент эта система является подтверждением концепции и поэтому является очень простой и хрупкой. Но это показывает, что к AS3 можно приблизиться к системе стилей mixin / traits от Scala. Я сделал проект github для хранения кода, если кто-то заинтересован в запуске решения и изучении того, как оно было сделано.
Более полный пример приведен в вики проекта.
Посмотрите здесь, это работает, смешивается в методах и просто.
http://github.com/specialunderwear/as3-mixin
о, и это работает, когда вы компилируете в режиме as3.