Можно ли добавить поведение в динамический класс ActionScript 3 без наследования этого класса?

Я хотел бы сделать что-то вроде следующего:

FooClass.prototype.method = function():String
{
    return "Something";
}

var foo:FooClass = new FooClass();
foo.method();

То есть, я хотел бы расширить сгенерированный класс с помощью одного метода, не через наследование, а через прототип.

Класс генерируется из WSDL, это не динамический класс, и я не хочу касаться сгенерированного кода, потому что он все равно будет перезаписан.

Короче говоря, я хотел бы иметь моральный эквивалент C # 3: методы расширения для AS3.

Изменить: я принял ответ AIB, потому что он соответствует тому, что я спрашивал лучше всего - хотя при дальнейшем размышлении это не решает мою проблему, но это моя вина, что я задал неправильный вопрос. :) Кроме того, обновления для хороших предложений.

10.08.2008 15:05:33
@aib прав, я сделал ошибку, когда проверил это. Я забыл, что прототип доступен только для класса, а не для каждого объекта, поэтому я получил ошибки во время выполнения. Тем не менее, мое решение обертки не подклассов, это обертки. Класс-обертка расширяет только оригинал, так что он будет иметь тот же тип.
Theo 14.08.2008 20:39:16
5 ОТВЕТОВ
РЕШЕНИЕ

Да, такая вещь возможна.

На самом деле, ваш пример очень близок к решению.

Пытаться

foo["method"]();

вместо того

foo.method();
3
12.08.2008 14:31:44

@aib, к сожалению, неверен. Предполагая строгий режим (режим компилятора по умолчанию), невозможно изменить прототип нединамических типов классов в ActionScript 3. Я даже не уверен, что это возможно в нестрогом режиме.

Является ли обертывание вариант? По сути, вы создаете класс, который принимает один из объектов, которые вы получаете от веб-службы, и просто перенаправляет все вызовы методов, но также имеет свои собственные методы:

public class FooWrapper extends Foo {

    private var wrappedFoo : Foo;

    public function FooWrapper( foo : Foo ) {
        wrappedFoo = foo;
    }

    override public function methodFromFoo( ) : void {
        wrappedFoo.methodFromFoo();
    }

    override public function anotherMethodFromFoo( ) : void {
        wrappedFoo.anotherMethodFromFoo();
    }

    public function newMethodNotOnFoo( ) : String {
        return "Hello world!"
    }

}

Если вы хотите работать с a Foo, но у вас есть дополнительный метод, который вам нужен, вы оборачиваете Fooэкземпляр в a FooWrapperи вместо этого работаете с этим объектом.

Это не самое удобное решение, там много печатания, и если сгенерированный код меняется, вам нужно изменить FooWrapperкласс вручную, но если вы не можете изменить сгенерированный код, чтобы включить нужный метод или сделать класс динамическим, я надеваю не вижу, как это можно сделать.

Другое решение - добавить в процесс сборки шаг, который изменяет источник сгенерированных классов. Я предполагаю, что у вас уже есть шаг, который генерирует код из WSDL, так что вы можете добавить шаг после этого, который вставит необходимые вам методы.

1
13.08.2008 15:38:07

@Theo: Как бы вы объяснили следующую работу в 3.0.0.477 со стандартным файлом flex-config.xml (<strict> true </ strict>) и даже с параметром -compiler.strict, переданным в mxmlc?

Foo.as:

package
{
    public class Foo
    {
        public var foo:String;

        public function Foo()
        {
            foo = "foo!";
        }
    }
}

footest.as:

package
{
    import flash.display.Sprite;

    public class footest extends Sprite
    {
        public function footest()
        {
            Foo.prototype.method = function():String
            {
                return "Something";
            }

            var foo:Foo = new Foo();
            trace(foo["method"]());
        }
    }
}

Обратите внимание, что OP сказал, что наследование было неприемлемо, так как изменял сгенерированный код. (Если бы это было не так, добавление «динамического» к определению класса, вероятно, было бы самым простым решением.)

3
14.08.2008 10:55:50

В зависимости от того, сколько методов у вашего класса, это может работать:

Актуальный класс:

public class SampleClass
{
    public function SampleClass()
    {
    }

    public function method1():void {
        Alert.show("Hi");
    }

Quick Wrapper:

var actualClass:SampleClass = new SampleClass();

var QuickWrapper:Object = {
    ref: actualClass,
    method1: function():void {
        this.ref.method1();
    },
    method2: function():void {
        Alert.show("Hello!");
    }   
};

QuickWrapper.method1();
QuickWrapper.method2();
2
14.08.2008 16:07:33

Исправление обезьяны - это (не элегантный) вариант.

Например, предположим, вам не нравится тот факт, что Flex 3 SpriteAsset.as возвращает метрики границы по умолчанию [7,7,7,7] (в отличие от flex 2). Чтобы это исправить, вы можете:

  1. Создайте копию SpriteAsset.as и добавьте ее в свой проект по адресу /mx/core/SpriteAsset.as.
  2. Отредактируйте свою локальную копию, чтобы исправить любые проблемы, которые вы найдете
  3. Запусти свой ап

Google " flex monkey patch " для большего количества примеров и инструкций.

1
17.09.2008 20:09:30