在AS3中实现Mixin或Trait?

Bef*_*rem 5 traits actionscript-3 mixins

我正在寻找有关如何在AS3中实现Mixin/Trait样式系统的想法.

我希望能够将多个类组合成一个对象.当然这不是AS3的语言级功能,但我希望有一些方法可以使用基于原型的技术或者一些字节码黑客,我相信AsMock用它来实现它的功能.

现有的Java示例是Qi4J,其中用户定义Qi4j框架基于元数据标签和按惯例编码实现的接口.

有没有人想知道如何在AS3中使用Mixin/Trait概念?

Bef*_*rem 7

零解决方案就此呈现,因此我研究了几种方法.通过将在其他对象上定义的方法添加到基础对象原型,有ECMA脚本样式混合.但这意味着静态类型的优势已经消失.

我一直在寻找一种不回避静态类型系统的解决方案.我知道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 
}
Run Code Online (Sandbox Code Playgroud)

然后定义类来表示这些接口:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

在您想要撰写课程的正常情况下,您会写:

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) }
}
Run Code Online (Sandbox Code Playgroud)

由于它是常规布局,因此可以使用代码轻松编写.这正是我的解决方案所做的,通过将等效字节码注入新类.使用这个字节码注入系统,我们可以像这样创建一个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)
    }
}
Run Code Online (Sandbox Code Playgroud)

目前,这个系统是一个概念证明,因此非常基本和脆弱.但它表明,有可能接近Scala mixin/traits样式系统到AS3.我已经创建了一个github 项目来保存代码,如果有人对运行解决方案感兴趣并且如何完成它.

在项目维基上给出了一个更完整的例子.