flex inheritance class share - apache-flex

//Base.as
public class Base
{
private var _foo:String;
[Bindable]
public function set foo(value:String):void
{
_foo = value;
}
public function get foo():String
{
return _foo;
}
/*
Many many setter/getter, methods, events
*/
}
//Control.as
public class MyControl extends Group
{
public function MyControl()
{
}
}
//Window.as
public class MyWindow extends spark.components.Window
{
public function MyWindow()
{
}
}
//Module
public class MyModule extends spark.modules.Module
{
public function MyModule()
{
}
}
I want to expose (friendly) Base properties, methods and events on the other classes. Something like this:
var window:MyWindow = new MyWindow();
window.foo = 'Hello World!';
var module:MyModule = new MyModule();
module.foo = 'bar';
<namespace:MyControl foo="Hello World!"/>
I don't want define all the properties in each class because they are many and the same for all of them.
Ideally would define something like:
public class MyControl extends Group, Base
{
public function MyControl()
{
}
}
(I know it can't be done.)
Thanks!
UPDATE:
Thanks again!
Maybe this clarify more my need... On business layer I have a variable called processID (and businessID, operationID, localityID, etc.) what be passed to Window from Menu, and Window passes it to Module. On Module Container, I have a CustomComponent what query database using this variable as parameter. This applied for all (almost) Components on Module. These variables are defined as level business layer, then I define a Class to store and manage these variables (and some related methods operating with these variables using business logic), so I can make a standalone class (or library) for every environment to reusing my common components. The idea is... insert a new CustomComponent and set these variables via mxml, like this:
<custom:MyCustomComponent id="zzz" processID="{processID}" businessID="{businessID}"/>
Module has the business logic for set (o not) any of the variables.
Otherwise, I would have to implement different logic for the CustomComponent (and Module) for read parent's variables and define these variables only in MyWindow (using composite pattern).

You can get your answer from following link -
http://flexinonroids.wordpress.com/2009/05/27/flex-3-dynamically-loading-components-at-runtime/
http://thecomcor.blogspot.in/2007/11/adobe-flex-dynamically-loading-classes.html
Or you can follow below approach -
1) Create an Interface as base
2) Extend your class with interface
3) Load class at runtime with SWFLoader.loaderContext.applicationDomain.getDefinition method
Thanks,
Varun

You can place your classes that require friendly access in the same package as your Base class, and define private fields without any access modifier( it is equivalent to internal modifier).
Otherwise, you can define your namespace like that:
namespace my_internal;
and then define class members like that:
my_internal var _foo:String;
after that, those members will be hidden for all code, except for code that contains
use namespace my_internal;
You can read more here:
http://help.adobe.com/en_US/ActionScript/3.0_ProgrammingAS3/WS5b3ccc516d4fbf351e63e3d118a9b90204-7f9e.html#WS5b3ccc516d4fbf351e63e3d118a9b90204-7f91
However, using 'friend access' can be an evidence of bad design, so if I were you I'd think twice before defining namespaces.
Update:
pseudo-superclass 1:
package proxy
{
public class Simple1
{
public var x:int;
public var y:int;
}
}
pseudo-superclass 2:
package proxy
{
import mx.controls.Alert;
public class Simple2
{
public var name:String = 'noname';
public function doAlert():void{
Alert.show(name);
}
//not normal method to replace 'this' with proxy
Simple2.prototype.doCrossClass = function doCrossClass():void{
Alert.show(''+(Number(this['x'])+Number(this['y'])));
}
}
}
Code for testing the result (looks as what you are expecting?):
var mega:Mega = new Mega();
mega.x = 100;
mega.y = 200;
mega.name = 'Multiple inheritance';
mega.doAlert();
mega.doCrossClass(); //300
And now pseudo-subclass with multiple inheritance:
package proxy
{
import flash.utils.Proxy;
import flash.utils.flash_proxy;
public dynamic class Mega extends Proxy
{
public function Mega()
{
super();
}
public var superArray:Array = [new Simple1(), new Simple2()];
flash_proxy override function getProperty(name:*):*{
for each(var superClass:Object in superArray){
if( name in superClass){
return superClass[name];
}
}
throw new Error('no such property');
}
flash_proxy override function setProperty(name:*, value:*):void{
for each(var superClass:Object in superArray){
if( name in superClass){
superClass[name] = value;
return;
}
}
throw new Error('no such property');
}
flash_proxy override function callProperty(name:*, ...args):*{
for each(var superClass:Object in superArray){
if( name in superClass){
var f:Function = superClass[name] as Function;
return f.apply(this, args);
}
}
throw new Error('no such function');
}
}
}
You can also want to use javascript-like class construction(i.e. just using simple Object and assigning properties and functions to it in any combinations you want).

Related

Haxe: Binding pattern with abstract fields access methods

I'd like to make wrapper to implement simple data binding pattern -- while some data have been modified all registered handlers are got notified. I have started with this (for js target):
class Main {
public static function main() {
var target = new Some();
var binding = new Bindable(target);
binding.one = 5;
// binding.two = 0.12; // intentionally unset field
binding.three = []; // wrong type
binding.four = 'str'; // no such field in wrapped class
trace(binding.one, binding.two, binding.three, binding.four, binding.five);
// outputs: 5, null, [], str, null
trace(target.one, target.two, target.three);
// outputs: 5, null, []
}
}
class Some {
public var one:Int;
public var two:Float;
public var three:Bool;
public function new() {}
}
abstract Bindable<TClass>(TClass) {
public inline function new(source) { this = source; }
#:op(a.b) public function setField<T>(name:String, value:T) {
Reflect.setField(this, name, value);
// TODO notify handlers
return value;
}
#:op(a.b) public function getField<T>(name:String):T {
return cast Reflect.field(this, name);
}
}
So I have some frustrating issues: interface of wrapped object doesn't expose to wrapper, so there's no auto completion or strict type checking, some necessary attributes can be easily omitted or even misspelled.
Is it possible to fix my solution or should I better move to the macros?
I almost suggested here to open an issue regarding this problem. Because some time ago, there was a #:followWithAbstracts meta available for abstracts, which could be (or maybe was?) used to forward fields and call #:op(a.b) at the same time. But that's not really necessary, Haxe is powerful enough already.
abstract Binding<TClass>(TClass) {
public function new(source:TClass) { this = source; }
#:op(a.b) public function setField<T>(name:String, value:T) {
Reflect.setField(this, name, value);
// TODO notify handlers
trace("set: $name -> $value");
return value;
}
#:op(a.b) public function getField<T>(name:String):T {
trace("get: $name");
return cast Reflect.field(this, name);
}
}
#:forward
#:multiType
abstract Bindable<TClass>(TClass) {
public function new(source:TClass);
#:to function to(t:TClass) return new Binding(t);
}
We use here multiType abstract to forward fields, but resolved type is actually regular abstract. In effect, you have completion working and #:op(a.b) called at the same time.
You need #:forward meta on your abstract. However, this will not make auto-completion working unless you remove #:op(A.B) because it shadows forwarded fields.
EDIT: it seems that shadowing happened first time I added #:forward to your abstract, afterwards auto-completion worked just fine.

adobe flex create child object given a parent object

i have the following 2 classes
class A {
var one:int;
}
class B extends A {
var two:int;
}
I now have an object of the class A but need to create and object of class B and set the additional parameters.
Does Flex allow child object creation given a parent object ?
note: there are lot of parameters in A so i don't want to copy individually each one.
Flex does allow multiple constructors, but it would take the form of copying each parameter in the constructor.
public class B extends A {
var two:int;
public function B(instanceA:A) {
this.one = instanceA.one;
//etc
}
}
Another approach could be to use ObjectUtil:
public class B extends A {
var two:int;
public function B(instanceA:A) {
var data = ObjectUtil.getClassInfo(instanceA);
for each (var prop in data.properties) {
this[prop] = instanceA[prop];
}
}
}
n.b. Check the excludes and options arguments of getClassInfo -- if there are properties that would cause problems to be processed in this way, you'll want to make sure to exclude them.

change Property Of **Custom Component Popup** From **Main.mxml**

I want to change Property Of Custom Component Popup From Main.mxml (Main Application)
My Custom Component is ->
public class PropertyPanel extends Panel
.....
in it I have
public function minimisePanel(e:MouseEvent):void{
effResize.heightTo = previousHeight;
effResize.widthTo = 200;
this.x = parentApplication.width - 320;
effResize.play([this]);
}
In Main Application I Called It As -->
private function AddPropertiesPanel():void{
var PropWindow:IFlexDisplayObject;
PropWindow = PopUpManager.createPopUp(this, Property_Panel, false);
/*Property_Panel is Property_Panel.mxml*/
}
And In Main Application I Want to -->
public function setCurrObj(event:TransformEvent):void{
/*Some Magical Stuff Required Here*/
}
Instead of storing the popup as a variable local to the function; store it as an instance variable on the Main.mxml class:
public var PropWindow:IFlexDisplayObject;
The AddPropertiesPanel() method will change like this:
private function AddPropertiesPanel():void{
PropWindow = PopUpManager.createPopUp(this, Property_Panel, false);
/*Property_Panel is Property_Panel.mxml*/
}
And then you can easily access properties on the panel instance in other methods:
public function setCurrObj(event:TransformEvent):void{
PropWindow.someProperty = someValue
}

structuremap enrichwith not overriden

I am trying to find a way to override a structuremap registry statement containing EnrichWith like so (here is the Registry class):
public class MyRegistry : Registry
{
public MyRegistry()
{
For(typeof(IMyList<int>)).EnrichWith(x => DecorateMyList(x)).Use(typeof(MyListA<int>));
For(typeof(IMyList<int>)).Use(typeof(MyListB<int>));
For<IMyList<string>>().Use<MyListA<string>>();
For<IMyList<string>>().Use<MyListB<string>>();
}
private object DecorateMyList(object o)
{
var genericParameters = o.GetType().GetGenericArguments();
var myListDecoratorType = typeof(MyListDecorator<>).MakeGenericType(genericParameters);
var decorated = Activator.CreateInstance(myListDecoratorType, new []{o});
return decorated;
}
}
public class MyRegistryUser
{
ObjectFactory.GetInstance<IMyList<string>>(); // Good: Returns an instance of MyListB<string> as expected
ObjectFactory.GetInstance<IMyList<int>>(); // Bad: Returns an instance of the decorator containing MyListB<int> - my second rule should have overridden the EnrichWith as well.
}
Am I right to think that there is a glitch in structure map or is there something I'm not seeing?
Thanks in advance

What event is fired when all SkinSparts are available in a SkinnableComponent?

I'm (slowly) learning Flex 4 and working on skinning a custom component that extends SkinnableComponent. The component is all in ActionScript and essentially looks like this:
package components
{
import spark.components.supportClasses.SkinnableComponent
[SkinState("normal")]
[SkinState("over")]
[SkinState("selected")]
public class AccountSummary extends SkinnableComponent
{
[Bindable]
public var itemIndex:int = 0;
[Bindable]
public var accountName:String = "";
[Bindable]
public var accountNumber:String = "";
[Bindable]
public var currentBalance:String = "";
[SkinPart(required="true")]
public var lblAccountName:Label;
[SkinPart(required="true")]
public var lblCurrentBalance:Label;
[SkinPart(required="true")]
public var lblAccountNumber:Label;
[SkinPart(required="true")]
public var lblLastUpdated:Label;
public function AccountSummary()
{
super();
lblAccountName.text = accountName;
lblCurrentBalance.text = currentBalance;
lblAccountNumber.text = "Acc: " + accountNumber;
lblLastUpdated.text = "Last Updated: ";
}
override protected function getCurrentSkinState():String
{
return "normal";
}
}
}
The issue I'm having is on NULL REFERENCES in the Constructor for the various SkinParts, because they're not created yet. I'm trying to find out when is the best time to access them to assign their .text values. I know I can override partAdded() and add the .text value as each part is added, but I'd rather just listen for some magic event that is dispatched when they're all available.
I'm not sure whether or not it matters, but the accountName, accountNumber variables are assigned by using a repeater with a dataProvider on the host component. I'm not sure if that too has something to do with when the data is available to the AccountSummary component - which may also needed to be waited on. I was able to successfully use FlexEvent.CREATION_COMPLETE to assign all my .text values to the SkinParts, but is that the right event/best practice? Any help would be greatly appreciated!
You need to read up on the Flex 4 Component LifeCycle, specifically the piece about component instantiation. Nothing will be created at the time the constructor executes. The values you are referencing (accountName, lblCurrentBalance. etc...) will not have moved beyond the default states either.
You want to set your default values in the partAdded() method. Rewrite your constructor code to something like this:
public function AccountSummary()
{
super();
}
override protected function partAdded(partName : String, instance: Object):void{
super.partAdded(partName, instance);
if(instance == lblAccountName){
lblAccountName.text = accountName;
else if(instance == lblCurrentBalance){
} else if (instance == lblCurrentBalance){
lblCurrentBalance.text = currentBalance;
} else if (instance == lblAccountNumber){
lblAccountNumber.text = "Acc: " + accountNumber;
} else if (instance == lblLastUpdated){
lblLastUpdated.text = "Last Updated: ";
}
}
If you're a new programmer, you may want to devote some time to learning some basic programming concepts. This ActionScript 3 Guide may help you get started. If you have experience in other languages, but are new to Flex, I strongly suggest spending a couple of days reading through the full flex documentation to help get your head around it.

Resources