Actionscript readonly variable - actionscript-3

How can I have a variable which is readonly from the outside but changeable from the inside?
Example code:
package
{
import flash.display.Sprite;
public class MyClass extends Sprite
{
[Bindable]
public var myVar:String;
public function MyClass()
{
myVar = "Some text here";
}
public function myfunc():void
{
myVar = "Some other text";
}
}
}
How can I make myVar to be readonly from the outside?
Thank you.

You'd need to create a getter function, but not a setter. However, to avoid warnings, you'll also need to make it as dispatching an event, and also dispatch the event when the value changes.
This would look like ...
protected var _myVar;
[Bindable("myVarChanged")]
public function get myVar():String {
return _myVar;
}
protected function setMyVar(value:String):void {
if(_myVar != value) {
_myVar = value;
dispatchEvent("myVarChanged");
}
}
Although it would be nice to have a public getter and a protected/private setter, that causes compilation errors.

Make it private, and create a getter with no setter:
private var _myVar:String;
public function get myVar():String {
return this._myVar;
}
I think you can use [Bindable] on the getter which will mean that the property will be a source for data-binding.

Related

Actionscript: Accessing private setter in own constructor

I am trying to set a variable whose setter is private in the constructor of the same class, but compiler keeps hitting me on the head with:
1059 Property is readonly
1178: Attempted access of inaccessible property gesamtBetrag through a
reference with static type ImmoObject.
package
{
public class Huhu
{
private var _prop1:int;
public function Huhu()
{
prop1 = 24;
}
public function get prop1():int
{
return _prop1;
}
private function set prop1(value:int):void
{
_prop1 = value;
}
}
}
Am I missing something here?
As stated, you cannot have a private setter and a public getter. The access modifier must be the same for getter and setter.
What you can do is only have a public getter and from within the class constructor or elsewhere you set the private variable directly:
class Foo {
private var _prop:int;
public function Foo() {
_prop = 24;
}
public function get prop():int { return _prop; }
}
(Note that in this case you could actually just initialize the private variable with a value, ex private _prop:int = 24.)
You could also expose other means of changing the private variable, such as a function or a setter with a different name:
class Foo {
private var _prop:int;
public function get prop():int { return _prop; }
protected function setProp(prop:int):void {
_prop = prop;
}
protected function set propValue(value:int):int {
_prop = value;
}
}
Edit: To be clear, access types must match for getter/setters of properties, but you can mix private/public access of getter/setter methods, in similar style as Java:
private prop:int;
public getProp():int { return prop; }
private setProp(value:int):void {
prop = value;
}
This is not as common of a style you see in AS3 because we have formal get/set property syntax, but it's still perfectly valid.
Getter/setter must have the same signature or else they are simply not related. You have a public getter and a private setter, as a result they are not related and the public getter has no setter so it is read only.

is it possible to change data provider of flex chart from a seperate ActionScript class?

Im trying to change flex chart data provider from seperate action script class? is it possible. i did not find any method to do that. any ideas guys ?
Yes you can. For that you need to have a reference to dataprovider of chart and it should be bindable. It means when you update dataProvider you view also will be update ( chart in this case ).
If it doesn't help you, I would see your code.
Yes, you can. A nice clean way is to have a custom event dispatcher facade:
package com.app.facades
{
import flash.events.Event;
import flash.events.EventDispatcher;
[Event(name="showDataInGrid" , type="com.app.events.GridEvent")]
public class GridFacade extends EventDispatcher
{
private static var _instance:GridFacade;
public function GridFacade(lock:SingletonLock, target:IEventDispatcher=null) {
super(target);
if(!(lock is SingletonLock)) {
throw(new Error("GridFacade is a singleton, please do not make foreign instances of it"));
}
}
public static function getInstance():GridFacade {
if(!_instance) {
_instance = new GridFacade(new SingletonLock());
}
return _instance;
}
}
}
class SingletonLock{}
create a dispatchable event like so:
package com.app.events {
import flash.events.Event;
import flash.events.IEventDispatcher;
public class DispatchableEvent extends Event implements IDispatchableEvent {
protected var _dispatcher:IEventDispatcher;
public function DispatchableEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false)
{
super(type, bubbles, cancelable);
}
public function dispatch():void
{
_dispatcher.dispatchEvent(this);
}
}
}
then have a custom GridEvent like so:
package com.app.events {
public class GridEvent extends DispatchableEvent {
public static const SHOW_DATA_IN_GRID:String = "showDataInGrid";
public var data:Object;
public function GridEvent(type:String,
data:ArrayCollection = null,
bubbles:Boolean=false,
cancelable:Boolean=false) {
super(type,bubbles,cancelable);
_dispatcher = GridFacade.getInstance();
this.data = data;
}
}
}
then listen for the showDataInGrid event in the scope of your grid component:
...
GridFacade.getInstance().addEventListener(GridEvent.SHOW_DATA_IN_GRID, onShowDataInGrid);
...
protected function onShowDataInGrid(event:GridEvent):void {
myGrid.dataProvider = event.data;
// refresh the collection so that the component will display the new data
event.data.refresh();
// remember to reset any data specific stuff you may have set in the grid component before doing this.
}
to actually change the data, in any class you wish do the following:
(new GridEvent(
GridEvent.SHOW_DATA_IN_GRID,
someCollectionToShowInTheGrid,
)).dispatch();
And watch the magic! :)
good luck!

AS3 override public function both are called?

I am a little confused by this concept.
If I override a public function in a base class, I would have thought that this override function is called and the original is ignored? though this doesn't seem to be the case...
public class AbstractScreen extends Sprite
{
public function AbstractScreen()
{
}
public function updateLanguage():void
{
trace("WARNING: need to override public function updateLanguage()");
}
}
public class Start extends AbstractScreen
{
override public function updateLanguage():void
{
title.text = _model.language.start
title.setTextFormat(titleFormat);
}
}
public class ViewManager extends Sprite
{
private var _model:Model;
private var _screens:Array;
public function ViewManager(model:Model)
{
_model = model;
_model.addEventListener(AppEvent.INIT_VIEW, initViews);
_model.addEventListener(AppEvent.UPDATE_VIEW, updateView);
_model.addEventListener(AppEvent.CHANGED_LANGUAGE, changeLanguage);
}
private function initViews(e:AppEvent):void
{
trace("View Manager: initViews");
_screens = new Array(new Start(_model), new TakePhoto(_model));
dispatchEvent(new ViewEvent(ViewEvent.VIEW_READY));
}
private function changeLanguage(e:AppEvent):void
{
for each (var screen:AbstractScreen in _screens)
{
screen.updateLanguage();
}
}
}
If my model dispatches a CHANGED_LANGUAGE event, the text in the views gets updated, But I also get a trace of "WARNING: need to override public function updateLanguage()" What could I be doing wrong?
You are right, this should not call the base class function. Are you sure there is no call to
super.initLanguage()
within your override?
Most IDE's add this call in the function body automatically, if they create an override for you.
EDIT
From your edit I see your are iterating over two objects of the types Start and TakePhoto. I assume TakePhoto is also derived from AbstractScreen and the trace may be comming from this one.
Also I suggest to use the abstract base class in your iteration.
for each (var screen:AbstractScreen in _screens)
{
screen.updateLanguage();
}

referencing variable in document class from another class

I need to increment an integer variable in a function within the document class upon transpiring event in another class. I can't seem to figure out how to call the function and reference the variable.
as3 newbie, please help!
The proper scope needs to be in place and the proper packaging.
Declare a static variable to handle your access to the Main Document Class
private static var _instance:Main;
public static function get instance():Main { return _instance; }
public function Main() { // constructor
_instance = this;
}
Declare some getters and setters in the Main Document Class
private var _foo:int = 0;
public function get foo():int{
return _foo;
}
public function set foo(value:int):void {
_foo= value;
}
And then in any class you need you can change to something as follows,
public class O {
public function O() {
Main.instance.set(Main.instance.get() + 1);
}
}
simple example, defining a variable 'test' in the document class:
package {
public class DocumentClass extends Sprite {
public static var test:Number = 3;
public function DocumentClass() {
test = 4;
}
}
}
now access the 'test' variable in another class:
package {
public class OtherClass extends Sprite {
public function OtherClass() {
DocumentClass.test = 5;
}
}
}
does this apply to your code?

Override Clone() in custom event for AS3... need help

I have created a custom even class which is pretty basic. But when calling an event and then relaying that event to another class I have encountered the "cannot transform thisEvent into thisOtherEvent" error.
I realize this is because I needed to override the Clone function in my custom event like so:
package com
{
import flash.disply.*;
import flash.events.Event;
public class MyCustomEvents extends Event
{
public static const SOME_EVENT:String = "some_event";
public var info:Object;
public function MyCustomEvents($type:String, $info:Object,$bubbles:Boolean = false, $cancelable:Boolean = false)
{
super($type, $bubbles, $cancelable);
this.info = $info;
}
public override function clone():Event {
return new MyCustomEvents($type, $bubbles, $cancelable);
}
}
}
However I am still getting this error when I dispatch the event. Anything else I might be missing?
here is the error:
TypeError: Error #1034: Type Coercion failed: cannot convert com.greensock.events::TransformEvent#d8df709 to com.customEvents.MyCustomEvents.
I tried casting the event in the code like so:
var deleteImgEvent:MyCustomEvent = new MyCustomEvent(MyCustomEvents.IMAGE_DELETE, {imgData: getImg}, true, false); this.dispatchEvent(deleteImgEvent as MyCustomEvents);
Still no luck.
UPDATE:
Ok, seems like the problem is in the greensock Transform library. When the event handler for my custom event is called, I run a function of the TransformManager class.
_manager.deleteSelection();
Inside that class it dispatched a TransformEvent. Not sure why, but it is reading that delete event as a MyCustomEvent.
/**
* #usage
* var myEvent:CustomEvent = new CustomEvent(CustomEvent.EVENT_TYPE_A, { integerRelatedToEvent: 5, stringRelatedToEvent: 'easy' });
* addEventListener(CustomEvent.EVENT_TYPE_A, traceCustomEvent);
* dispatch(myEvent);
* function traceCustomEvent ($e:CustomEvent):void {
* trace($e.type);
* }
*/
package {
import flash.events.Event;
public class CustomEvent extends Event {
// Types:
public static const EVENT_TYPE_A:String = 'CustomEvent.EVENT_TYPE_A';
public static const EVENT_TYPE_B:String = 'CustomEvent.EVENT_TYPE_B';
// Components:
private var _customDatum:Object;
public function get customDatum ():Object { return _customDatum; }
public function CustomEvent ($type:String, $customDatum:Object) {
super($type);
_customDatum = $customDatum;
}
public override function clone ():Event {
return new CustomEvent(type, _customDatum);
}
}
}
"When creating your own custom Event
class, you must override the inherited
Event.clone() method in order for it
to duplicate the properties of your
custom class. If you do not set all
the properties that you add in your
event subclass, those properties will
not have the correct values when
listeners handle the redispatched
event."
package com.events;
{
import flash.events.Event;
public class XMLLoaderEvent extends Event
{
public static const XML_LOADED:String = "XML_Loaded";
public var data:*;
public var properties:Object;
public function XMLLoaderEvent( type:String,_data:*,bubbles:Boolean = false,cancelable:Boolean = false):void
{
super( type, bubbles, cancelable );
data = _data;
}
// Override clone
override public function clone():Event
{
return new XMLLoaderEvent( type, data, bubbles, cancelable);
}
}
}
Don't know if that's it but you have an extra parameter $info:Object into your custom event, but you don't pass it in your clone contructor.
return new MyCustomEvents(type, info, bubbles, cancelable);
I think you need the clone function to return a MyCustomEvents type. Not an Event type. And you need to add the info parameter as stated by the previous poster.
package com {
import flash.display.*;
import flash.events.Event;
public class MyCustomEvents extends Event {
public static const SOME_EVENT:String = "some_event";
public var info:Object;
public function MyCustomEvents($type:String, $info:Object,$bubbles:Boolean = false, $cancelable:Boolean = false) {
super($type, $bubbles, $cancelable);
this.info = $info;
}
public override function clone():MyCustomEvents {
return new MyCustomEvents(this.type, this.info, this.bubbles, this.cancelable);
}
}
}