2010-04-05 57 views
5

我正在寻找关于如何在AS3中实现Mixin/Trait样式系统的想法。AS3中的Mixin或Trait实现?

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

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

有没有人有关如何获得在AS3内Mixin/Trait概念工作的任何想法?

回答

7

提出了零解决方案,所以我研究了几种方法。通过将其他对象上定义的方法添加到基础对象原型中,有ECMA script style mixins。但这意味着静态打字的优势消失了。

我正在寻找一个解决方案,没有回避静态类型系统。我知道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的Scala mixin/traits风格系统。如果有人对运行该解决方案感兴趣,并且探讨它是如何完成的,我已经编写了github project来保存代码。

在项目wiki上给出了一个更完整的例子。

+0

我注意到您的链接不工作,所以我已经更新了他们。 – 2010-10-29 08:17:54

+0

不错,谢谢安德鲁;) – 2010-10-29 09:55:52

1

看这里,这个工程,混合方法和简单。

http://github.com/specialunderwear/as3-mixin

O,当你在AS3模式下编译它的工作原理。

+0

不错的想法,我会给我的下一个as3项目测试运行。 – 2010-10-16 10:34:54

+0

不幸的是,这样做并不能帮助类型检查器:(。 – 2010-10-17 08:58:30

+0

由于mixin是外部类,它们对mix​​in方法所在类的类型没有任何影响,这是mixin的一个特性,而不是这个特定的实现,如果你想让你的类的类型定义它的功能(唯一的),你不应该使用混合类, – specialunderwear 2010-11-05 05:25:51