How to instantiate an array of custom classes in Action Script 3.0 - actionscript-3

I'm new to AS3 and I'm getting this error while trying to implement OO style code.
Incorrect number of arguments. Expected no more than 0.
When I try to:
var countries:Country = new Country(10);
Normally this would work in Java or C++, so I'm not sure what's up!?
Here is my custom class.
package {
public class Country {
var cName:String = "noName";
public function Country() {
// constructor code
}
public function setName(n:String):void {
cName = n;
}
public function getName():String {
return cName;
}
}
}

You are passing 10 to the constructor, which is not what you want to do. To instantiate an array of instances, try something like this:
var countries:Array = []
var country:Country;
for (var i:uint = 0; i < 10; i++) {
country = new Country()
country.setName("Country_" + i);
countries.push(country)
}

your constructor function public function Country() {} not have an argument, but you give 10, must go wrong.
ActionScript's array not like c++, don't need element type <Country>
you want to save class in array is simple: var arr:Array = [new Country()]

Related

Nonfunctioning "for loop" for addressing each variable of class

I'm learning AS3 but have some antiquated background in programming (TP and Atari Basic). On this forum I learned to use a loop such as the one below to address each variable in an object class, in order to make a clone of the object (deep or shallow) or in my case to build the text for a tooltip. However mine doesn't work. Here's the loop, following is an explanation, any help you can give I'd appreciate greatly!
var tooltipText:String;
var i:String;
for (i in bsm) {
if (!(bsm[i] is String)) {
if (bsm[i] != 0) {
tooltipText = i + ": " + bsm[i];
tooltip.extendTooltip(tooltipText, 0xFFFFFF);
}
}
}
Please forgive the horrible variable names. 'i' is a String. 'bsm' is a non-null instance of class StatMod, which begins with
public class StatMod extends Object {
public static const ENCHANTMENTMODIFIER:String = "enchantmentModifier";
public var enchantmentType:String = "None";
public var enchantmentDescriptor:String = "None";
public var minDamage:Number = 0;
public var maxDamage:Number = 0;
public var attackSpeed:Number = 0.2;
The intended behavior is to go through each of the variables of StatMod (I'm not showing them all and I will add more later), and if the variable is a non-zero number, make a string ("attackSpeed: 0.2" for instance) and then add that string to the tooltip. The tooltip.extendTooltip function is working properly.
The observed behavior is basically the computer believing that there are no variables in bsm.
What can I say or do to convince the computer that there actually are variabels in bsm?
The behavior you're expecting is only the case when iterating over dynamically attached properties. For example, if you marked your class dynamic:
public dynamic class StatMod { }
Then added some values to it at runtime:
bsm.test = 5;
Your loop will find the property test with the value 5.
Some options you have to achieve what you want are:
Extend the Proxy class to define what properties are iterable via nextName and nextNameIndex.
Use describeType to generate a list of all the public properties.
Though a simpler method is to expose a list of the properties you want to iterate over and use that in your loop instead, something like:
public class StatMod {
// Existing properties etc.
private _properties:Vector.<String>;
public function get properties():Vector.<String> {
if (_properties === null) {
_properties = new <String>[
'enchantmentType',
'enchantmentDescription',
'minDamage',
'maxDamage',
'attackSpeed'
];
}
return _properties;
}
}
Then:
for (var i:int = 0; i < bsm.properties.length; i++) {
var prop:String = bsm.properties[i];
trace(prop, bsm[prop]);
}

Sorting an array by a private variable

So... I have spent the last hour trying to figure out why the sort method for my array was not working properly, when I realized that the variable I was trying to sort by in my objects was not publicly available. I have accessed it by using a getter method, which has worked fine for all other purposes. My questions is: Is it possible to sort by a private variable somehow? Perhaps by using a getter method, but I don't know how that would work syntactically. Or do I just have to make my variable public?
On a slightly related note, is there some way to sort on a variable of an object in a vector using standard methods?
Here is an example using get function to sort
var k:Vector.<A> = new Vector.<A>();
k.push(new A(5));
k.push(new A(3));
k.push(new A(7));
k.push(new A(1));
k.push(new A(9));
k.sort(compareFunction);
private function compareFunction(obj1:Object, obj2:Object, properties:Array = null):int
{
var a1:A = obj1 as A;
var a2:A = obj2 as A;
if (a1.level > a2.level)
{
return 1;
}
else if (a1.level < a2.level)
{
return -1;
}
else
{
return 0;
}
}
class A {
private var _level:int;
public function get level():int
{
return _level;
}
public function A($level:int)
{
_level = $level
}
}

how to pass argument to Marionette.CompositeView

how to pass a values dynamically to an Marionette.CompositeView during run time? like in java we create a method like the following
package com.test.poc;
public class SampleMethod {
public int add(int a, int b) {
return a + b;
}
public static void main(String[] args) {
SampleMethod method = new SampleMethod();
int firstValue = 90, secondValue = 90;
System.out.println("add : " + method.add(firstValue, secondValue));
}
}
the above is the simple java code anybody can understand like the above how to create and pass arguments to Marionette.CompositeView and work on them?
Best Regards
at the moment you instanciate a view, you can pass whatever arguments you want. normally you pass the model and the collection to be rendered in the compositeView, but you can pass more data if you need.
var MyCompositeView = Backbone.Mationette.CompositeView.extend({
initialize : function (options){
this.dataValue = options.dataValue1;
this.helperObject = options.helperObject;
this.useValues();
},
useValues: function () {
console.log(this.dataValue);
}
});
var helperObject = {
value3 : "I have a value",
value4 : "I dont!"
}; /// a js object literal
var myModel = new MyModel();
var myCollection = new MyCollection();
var myCompositeView = new MyCompositeView({model:myModel,
collection:myCollection,
helperObject:helperObject,
dataValue1:"Hi there"});
notice that Im passing 4 values in the at the time to intanciate the view, and Im reading just two of them, the model and the collection will be handled by marionette, but the other two you can read them in your initialize function.
hope that helps.

Get AS3 instance method reference from Class object

class Foo {
public function bar():void { ... }
}
var clazz:Class = Foo;
// ...enter the function (no Foo literal here)
var fun:Function = clazz["bar"]; // PROBLEM: returns null
// later
fun.call(new Foo(), ...);
What is the correct way to do the above? The Java equivalent of what I want to do is:
Method m = Foo.class.getMethod("bar", ...);
m.invoke(new Foo(), ...);
Actual code (with workaround):
class SerClass {
public var className:String;
public var name:String;
private var ser:String = null;
private var unser:Function = null;
public function SerClass(clazz:Class):void {
var type:XML = describeType(clazz);
className = type.#name;
// determine name
name = type.factory.metadata.(#name=="CompactType").arg.(#key=="name").#value;
// find unserializer
var mdesc:XML = XML(type.method.metadata.(#name=="Unserialize")).parent();
if (mdesc is XML) {
unser = clazz[mdesc.#name];
}
// find serializer
var sdesc:XML = XML(type.factory.method.metadata.(#name=="Serialize")).parent();
if (sdesc is XML) {
ser = sdesc.#name;
}
}
public function serialize(obj:Object, ous:ByteArray):void {
if (ser == null) throw new Error(name + " is not serializable");
obj[ser](ous);
}
public function unserialize(ins:ByteArray):Object {
if (unser == null) throw new Error(name + " is not unserializable");
return unser.call(null, ins);
}
}
Here the function bar only exist when your class is instanciated :
var foo:Foo = new Foo()
var fun:Function = foo.bar // <-- here you can get the function from the new instance
if you want to access it directlty you have to make it static:
class Foo {
public static function bar():void{ ... }
}
now you can access your function from the class Foo:
var fun:Function = Foo.bar
or
var clazz:Class = Foo
var fun:Function = clazz["bar"]
I am not sure about what you are intending to do.
However AS3Commons, especially the reflect package have API's that let you work with methods, instances and properties of a class.
There are also API methods to create instances of certain class types on the fly and call their respective methods.
Cheers
It's not
fun.call(new Foo(), ...);
Use instead since no parameters are required for the function
fun.call(clazz);
The first parameter as specified by adobe docs.
An object that specifies the value of thisObject within the function body.
[EDIT]
Forgot to point out you have to instantiate a non-static class with the "new" keyword.
var clazz:Class = new Foo();
[EDIT2]
Ok I played around and think I got what you want.
base.as
package{
public class Base {
public function Base() {
trace('Base constructor')
}
public function someFunc( ){
trace('worked');
}
}
}
//called with
var b:Base = new Base( );// note I am not type casting to Class
var func:Function = b.someFunc;
func.call( );
My workaround is to store the function name instead of the Function object.
var fun:String = "bar";
// later...
new Foo()[fun](...);

AS3 Custom Object to ByteArray then to Custom Object

Having problem reading bytearray of custom objects. Any help is appreciated
public class CustomObject extends Object {
public function CustomObject() {
public var _x:Number = 100
public var _y:Number = 10
public var _z:Number = 60
}
}
var cObj:CustomObject = new CustomObject()
var bytes:ByteArray = new ByteArray()
bytes.writeObject(cObj)
bytes.compress()
//read
try { bytes.uncompress() } catch (e:Error) { }
var obj:CustomObject = bytes.readObject() as CustomObject
trace(obj) // null why?!
trace(obj._z) // Obviously - TypeError: Error #1009: Cannot access a property or method of a null object reference.
What you want to do is use the registerClassAlias method to register type information along with the data. That way Flash will know how to serialize/deserialize your object. Here's some sample code from Adobe's documentation:
registerClassAlias("com.example.eg", ExampleClass);
var eg1:ExampleClass = new ExampleClass();
var ba:ByteArray = new ByteArray();
ba.writeObject(eg1);
ba.position = 0;
var eg2:* = ba.readObject();
trace(eg2 is ExampleClass); // true
It should be noted that all types that should be serialized must be registered for the type information to be saved. So if you have another type that is referenced by your type, it too must be registered.
Your CustomObject class is wrong , it should throw an error actually , it should be this instead
public class CustomObject
{
public var _x:Number = 100
public var _y:Number = 10
public var _z:Number = 60
public function CustomObject()
{
}
}
Edit:
Sounds like macke has a point, because this works...
//read
try { bytes.uncompress() } catch (e:Error) { }
var obj:Object = bytes.readObject();
trace(obj) // [object Object]
trace(obj._z) // 60
Look at object that ByteArray.readObject() returns. You'll probably see that all properties are there, but type information is lost. So, you can solve this by creating some
public static function fromObject(value:Object):CustomObject {
var result:CustomObject = new CustomObject();
result._x = value._x;
//and so on...
return result;
}
To serialize custom classes to the ByteArray, you must put registerClassAlias in the constructor of the class calling the byteArray.writeObject() function.
If you don't, your custom class will be serialized as Object type. I was calling registerClassAlias in the serialize function below and my custom class keeps getting serialized as Object until I moved the registerClassAlias to the constructor.
public class MyClass{
public function MyClass(){
registerClassAlias("com.myclass", MyClass); // Ok, serializes as MyClass
serialize( new MyClass() );
}
private function serialize( _c:MyClass ){
var byteArray:ByteArray = new ByteArray();
byteArray.writeObject( _c );
//registerClassAlias("com.myclass", MyClass); Not ok, serialized as Object
EncryptedLocalStorage.setItem('key', byteArray);
}
}