【问题标题】:Mixin or Trait implementation in AS3?AS3 中的 Mixin 或 Trait 实现?
【发布时间】:2011-02-04 09:00:35
【问题描述】:

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

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

一个现有的 Java 示例是 Qi4J,其中用户定义 Qi4j 框架根据元数据标签和约定编码实现的接口。

有没有人知道如何让 Mixin/Trait 概念在 AS3 中发挥作用?

【问题讨论】:

    标签: actionscript-3 mixins traits


    【解决方案1】:

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

    我一直在寻找一种不回避静态类型系统的解决方案。我知道ASMock 使用字节码注入来创建代理类。在过去的几天里,我在ASMock 附近进行了黑客攻击,并提出了一个可能的解决方案,通过创建一个具有组合类的类(通过字节码注入)来实现。

    从用户的角度来看,这涉及到通过许多接口定义使用 mixin 的对象:

    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这个项目上给出了一个更完整的例子。

    【讨论】:

    • 我注意到你的链接失效了,所以我更新了它们。
    【解决方案2】:

    看这里,这很有效,混合了方法并且很简单。

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

    o,当你在 as3 模式下编译时它可以工作。

    【讨论】:

    • 好主意,我将在我的下一个 as3 项目中对其进行测试。
    • 不幸的是,这样做对类型检查器没有帮助:(。
    • 因为 mixins 是外来的类,它对你使用 mixin 方法的类的类型没有任何影响,这是 mixins 的一个特性,而不是这个特定的实现。如果你想让你的类的类型定义它的功能(唯一),你不应该使用 mixins。
    • 更进一步,我认为您正在寻找的,将功能添加到目标类的类也有助于类的类型,称为多重继承。根据定义,mixin 不会影响目标类的类型。
    【解决方案3】:

    我在 Realaxy 中找到了这个——http://realaxy.com/

    【讨论】:

      猜你喜欢
      • 2019-08-11
      • 1970-01-01
      • 1970-01-01
      • 2023-03-06
      • 2015-04-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多