I want to create a internal ctor for class in ActionScript3 to make it immutable. I want that only another builder class will be allow to create instances of this immutable class.
I try to find the answer in Adobe's ActionScrtip 3 specification but it does not explain what happen when no public namespace (accessible) is define for ctor.
Immutable object:
package {
public class Immutable {
private var _value1:int;
private var _value2:int;
private var _value3:int;
public function Immutable(value1:int, value2:int, value3:int) {
_value1 = value1;
_value2 = value2;
_value3 = value3;
}
public function get value1():int {
return _value1;
}
public function get value2():int {
return _value2;
}
public function get value3():int {
return _value3;
}
}
}
As for access modifiers, internal is default.
The internal attribute is similar to the default access control in Java, although in Java there is no explicit name for this level of access, and it can be achieved only through the omission of any other access modifier. The internal attribute is available in ActionScript 3.0 to give you the option of explicitly signifying your intent to make a property visible only to callers within its own package.
As for constructor, you can't specify internal. If you omit access modifier, by default constructor will be accessible (public)
Related
Hi my problem is i have to be able to reference certain fields inside my Customer object.]
I am studying AS3 at the moment and being taught custom classes, but we are taught to use the toString method of returning a value i guess you could call it, what i need is to be able to call one field to identify the object i.e. name field from the object in the array, here's my code
package valueObjects
{
public class Person
{
//instance variables
protected var name:String;
protected var address:String;
protected var phoneNo:String;
public function Person(n:String,a:String,p:String)
{
name=n;
address=a;
phoneNo=p;
}
public function toString():String
{
//returns string
return name+":"+address+":"+phoneNo;
}
}
}
some reason it will not put that whole block of code together like THIS IS
So now how do i define it not toString but in object form ??
I think what you are trying to do is access the name, address and phoneNo vars from a different class?
If so, you have to declare them as public vars instead of private vars.
public var name:String; //now this can be accessed from other classes: thisClassInstance.name
If you want to have them read-only from other classes, you have to use a getter method:
protected var name_:String; //local var name for full access;
public function get name():String {
return name_; //this can be access by doing thisClassInstance.name
}
Does anyone know of a framework, preferably some way to have the Flex compiler run an extension or perhaps just a build step that we could generate strongly typed proxy classes of our application's data models.
There are 2 main things we want to do with the proxy's:
At runtime we want to lazily parse and instantiate the instance as accessed (similiar to how Java's Hibernate has Lazy proxy objects)
In an editor application we want to implement setter calls so we can track which objects have been modified
The Proxy is really necessary in this situation beyond things like programatically setting up ChangeWatcther's because we need to track Array adds/remove and possibly track "reference" objects so that when a "reference key" is changed we know to save those objects that are referencing it by key
In the first case we want the proxy to basically abstract when that object is loaded from serialized data, but still pass around references of it with the same public properties and data access pattern if it were the real object.
Basically the proxy would instantiate the object the first time a method is called on it.
I know we could use some AS3 byte-code libraries like as3-commons-bytecode.
Or possibly repurposing the GraniteDS Code Generation.
I'd prefer to generate code because it is a deterministic thing and it'd be nice if we could have a way to debug it at runtime easier.
Does anyone know if I could do something like MXMLC does when it generates AS3 code from MXML files.
Also is there anyway to control "when" in the compilation pipeline I can generate code, because we have a lot of data objects using public fields instead of getter/setters, but that are [Bindable] and so if I could generate the proxy based on the generated getter/setter methods that would work.
Here's an example application data object and proxy classes:
[Bindable]
public class PersonDTO implements Serializable {
private var _name:String;
private var _age:Number
public function get age():Number {
return _age;
}
public function set age(a:Number):void {
_age = a;
}
public function get name():String {
return _name;
}
public function set name(n:String):void {
_name = n;
}
public void readObject(data:*) {
//...
}
}
// GENERATED CLASS BASED ON PersonDTO
public class LazyProxy_PersonDTO extends PersonDTO {
private var _instance:PersonDTO = null;
private var _instanceData:*;
private function getInstance():void {
if (_instance == null) {
_instance = new PersonDTO();
_instance.readObject(_instanceData);
}
}
override public function get age():Number {
//Ensure object is instantiated
return getInstance().age;
}
override public function get name():String {
//Ensure object is instantiated
return getInstance().name;
}
}
// GENERATED CLASS BASED ON PersonDTO
public class LogChangeProxy_PersonDTO extends PersonDTO {
//This will be set in the application
public var instance:PersonDTO;
//set by application
public var dirtyWatcher:DirtyWatcherManager;
override public function set age(a:Number):void {
dirtyWatcher.markAsDirty(instance);
instance.age = a;
}
}
Digging a little deeper into AS3-Commons byte code library it looks like they support generating proxy classes and interceptors.
http://www.as3commons.org/as3-commons-bytecode/proxy.html
public class DirtyUpdateInterceptor implements IInterceptor {
public function DirtyUpdateInterceptor() {
super();
}
public function intercept(invocation:IMethodInvocation):void {
if (invocation.kind === MethodInvocationKind.SETTER) {
if (invocation.arguments[0] != invocation.instance[invocation.targetMember]) {
invocation.instance.isDirty = true;
}
}
}
}
I read a question on stackoverflow (couldn't find it now) about how variables in a method can be only accessed in that method, but the code still works with the answer being an analogy of a hotel room. In AS3, I believe everything that's not primitive gets passed as a reference. So, the following code would be the same as that question and isn't guaranteed to work?
public class Testy {
private var foo:Array;
public function Testy(input:Array) {
// Allow the whole class to access it
foo = input;
}
public function traceFoo(){
trace(foo);
}
}
Now, foo would be a reference to the input argument in the class' constructor. Is this safe code/good practice? Thanks!
Yes this is safe/good code practice as long as you don't want to manipulate the original Array. If you want to manipulate the original array, allow public access to the array by making it a public var or using a public getter/setter.
What you've described is a property, and is inline with encapsulation of object oriented programming.
This would expose a getter and setter:
package
{
import flash.display.Sprite;
public class Testy extends Sprite
{
private var _foo:Array;
public function get foo():Array
{
return _foo;
}
public function set foo(value:Array):void
{
_foo = value;
}
public function Testy()
{
super();
}
}
}
Also it's better to return _foo.concat() in getter not to break encapsulation.
How can i produce the same output as specified below using the TypedFactoryFacility?
public class Something
{
public void Initialize(Whatever instance) {}
}
public interface ISomethingFactory
{
Something Create(Whatever instance);
}
internal class SomethingFactory : ISomethingFactory
{
private readonly IWindsorContainer _container;
public SomethingFactory(IWindsorContainer container)
{
_container = container;
}
public Something Create(Whatever instance)
{
Something item = _container.Resolve<Something>();
item.Initialize(instance);
return item;
}
}
So I want to replace the manual factory with a proxy-generated ITypedFactoryFacility, but I cant find a way to invoke something on the resolved component after creation. I looked at commission-concerns, but you don't have a reference to the CreationContext from a custom commision concern so that won't work. I could of course move the dependency to the ctor and provide an ctor override, but I think properties are good when you want to convey non-optional dependencies.
You don't need to invoke stuff on the instance upon creation - Windsor will automagically inject stuff when the name of the parameter in the factory method signature matches something that can be injected - be it constructor paramaters or public properties... short example (using a public property):
interface ISomeFactory
{
Something CreateSomething(object dataSource);
}
class Something
{
public object DataSource { get; set; }
}
Given that these are registered like this:
container.Register(Component.For<ISomeFactory>().AsFactory(),
Component.For<Something>().Lifestyle.Transient)
you can resolve instances of Something like this:
var aintThatSomething = someFactory.CreateSomething(new [] {"ZOMG!", "w00t!"});
Remember that if something inside the burden associated with the instance of Something requires decommissioning, you need to provide an appropriate Release method on the factory as well.
i've never tried to do this before, so my head a swimming a bit. i'd like to have a public boolean called enabled in myClass custom class. if it's called to be changed, how do i trigger a function from the change?
should i add an Event.CHANGE event listener to my variable? can i do that? or is there a more standard way?
We usually use properties for that.
Properties are just like public variables for the outside -- you can set instance.enabled = true; and so forth.. But you define properties as getters and/or setters functions for the class.
They are the perfect place for custom logic to be executed on value changes.
For example:
public class CustomClass {
private var _enabled:Boolean = false;
public function set enabled(value:Boolean):void {
trace('CustomClass.enabled is now', value);
this._enabled = value;
}
public function get enabled():Boolean {
trace('CustomClass.enabled was retrieved');
return this._enabled;
}
}
Note that they can't have the same name as your private variable and you don't need both of them defined. Actually, you don't even need a variable for a setter/getter. You could use them just like any function -- they just supply you with a different syntax.
For example:
var object:CustomClass = new CustomClass();
object.enabled = false;
if (object.enabled) {
...
}
They are great to expose a simple API, keeping you from rewriting outside code if the class' internals have to change.
AS3 Reference on getters and setters.