2008-08-10 11 views
5

Lo que me gustaría hacer es algo como lo siguiente:¿Es posible agregar comportamiento a una clase de ActionScript 3 no dinámica sin heredar la clase?

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

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

es decir, me gustaría extender una clase generada con un solo método, no a través de la herencia sino a través del prototipo.

La clase se genera a partir de WSDL, no es una clase dinámica, y no quiero tocar el código generado porque se sobrescribirá de todos modos.

Para abreviar, me gustaría tener el equivalente moral de C# 3: s Métodos de extensión para AS3.

Editar: Acepté la respuesta de aib, porque encaja con lo que estaba pidiendo lo mejor, aunque con una mayor reflexión no soluciona realmente mi problema, pero esa es mi culpa por hacer la pregunta incorrecta. :) Además, upmods para las buenas sugerencias.

+0

@aib tiene razón, cometí un error cuando lo probé. Olvidé que el prototipo solo es accesible en la clase y no en cada objeto, así que para mí obtuve errores en tiempo de ejecución. Sin embargo, mi solución contenedora no está subclasificando, está envolviendo. La clase contenedora solo extiende el original para que tenga el mismo tipo. – Theo

Respuesta

3

Sí, tal cosa es posible.

De hecho, su ejemplo está muy cerca de la solución.

Trate

foo["method"](); 

en lugar de

foo.method(); 
1

@aib Sentimos incorrecta. Asumiendo el modo estricto (el modo de compilador predeterminado) no es posible modificar el prototipo de tipos de clases no dinámicas en ActionScript 3. Ni siquiera estoy seguro de que sea posible en modo no estricto.

¿Está envolviendo una opción? Básicamente, usted crear una clase que toma uno de los objetos que tienes desde el servicio web y simplemente reenvía todo el método llama a eso, sino que también tiene métodos propios:

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!" 
    } 

} 

Cuando se desea trabajar con un Foo, pero también tiene el método adicional que necesita para envolver la instancia Foo en un FooWrapper y trabajar con ese objeto en su lugar.

No es la solución más conveniente, hay mucha escritura y si el código generado cambia debe cambiar la clase FooWrapper a mano, pero a menos que pueda modificar el código generado para incluir el método que desea o para hacer la dinámica de clase no veo cómo se puede hacer.

Otra solución es agregar un paso a su proceso de compilación que modifique la fuente de las clases generadas. Supongo que ya tiene un paso que genera el código de un WSDL, entonces lo que podría hacer es agregar un paso después que inserte los métodos que necesita.

4

@Theo: ¿Cómo explicaría el siguiente trabajo en 3.0.0.477 con el flex-config.xml defecto (<estricta> cierto </estricta >) e incluso un parámetro -compiler.strict pasado a mxmlc?

Foo.as:

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

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

footest.como:

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"]()); 
     } 
    } 
} 

Tenga en cuenta que el OP decía que la herencia era inaceptable, como lo era modificar el código generado. (. Si ese no fuera el caso, la adición de "dinámico" a la definición de clase, probablemente sería la solución más fácil)

2

Dependiendo del número de métodos de su clase tiene, esto puede funcionar:

clase real:

public class SampleClass 
{ 
    public function SampleClass() 
    { 
    } 

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

Envoltura rápida:

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(); 
1

mono parches es una opción (poco elegante).

Por ejemplo, suponga que no le gusta el hecho de que Flex 3 SpriteAsset.as devuelve una métrica de borde predeterminada de [7,7,7,7] (a diferencia de flex 2). Para solucionar este problema, puede:

  1. Crear una copia de SpriteAsset.as y añadirlo a su proyecto en /mx/core/SpriteAsset.as
  2. Editar su copia local para solucionar cualquier problema que encuentre
  3. Ejecute su ap

Google "flex monkey patch" para obtener más ejemplos e instrucciones.

Cuestiones relacionadas