2010-04-05 62 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