我正在寻找有关如何在AS3中实现Mixin/Trait样式系统的想法。
我希望能够将多个类组合成一个对象。当然这不是AS3的语言级功能,但我希望有一些方法可以使用基于原型的技术或者一些字节码黑客攻击,我相信AsMock用它来实现它的功能。
现有的Java示例是Qi4J,其中用户定义Qi4j框架基于元数据标签和按惯例编码实现的接口。
有没有人想过如何在AS3中使用Mixin / Trait概念?
答案 0 :(得分:7)
提出了零解决方案,所以我研究了几种方法。通过在其他对象上定义的方法向基础对象原型添加ECMA script style mixins。但这意味着静态类型的优势已经消失。
我一直在寻找一种不回避静态类型系统的解决方案。我知道ASMock使用字节码注入来创建代理类。在过去的几天里,我在ASMock周围进行了攻击,并通过创建一个包含组合类的类(通过字节码注入)来实现可能的解决方案。
从用户的角度来看,这涉及通过许多接口定义使用mixins的对象:
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)
}
}
目前,这个系统是一个概念证明,因此非常基本和脆弱。但它表明,有可能接近Scala mixin / traits样式系统到AS3。我已经制作了一个github project来保存代码,如果有人对运行解决方案感兴趣并且开始探究它是如何完成的。
项目wiki上有一个更完整的例子。
答案 1 :(得分:1)
答案 2 :(得分:1)
我在Realaxy中找到了这个 - http://realaxy.com/