AS3 how do you send vars to the parent constructor of an inherited class? - actionscript-3

That title probably made no sense, so I'll try to explain.
Let's say I create a class in AS3, any class with some basic vars, and those vars are set through that classes constructor
so..
var class = new basicClass(var1, var2);
Now let's say I want to create a new class which inherits the basicClass's vars/methods etc, so new class has something like
public class betterClass extends basicClass
and maybe that also has some vars that are set via it's constructor.
Now what I'm confused about is, how do you set the parent classes (basicClass) vars or do anything through it's constructor by creating betterClass?
If basicClass has a constructor which expects values, then how do you set that up, by doing...
var class2 = new betterClass(var3, var4)
because var3 and var4 are for the constructor of betterClass, I don't see how an instance of basicClass is setup.
I know this is pretty basic stuff, it's just I've never needed to use inheritance before.

So you have got BasicClass, its constructor may look like this:
public function BasicClass(var1:*, var2:*)
{
//do some stuff with var1 and var2
}
//you can extend some metods too
public function niceFunction():void
{
trace('Oh! Hello!');
}
Now you can create BetterClass:
public function BetterClass(var3:*, var4:*)
{
super(var3, var4);
//this calls constructor of BasicClass
}
override public function niceFunction():void
{
super.niceFunction();
trace('Nice to meet you.');
//This will trace: Oh! Hello! Nice to meet you.
}

You can call the parent class's constructor from your extending class using the 'super' keyword'
public betterClass(){
super(constuctorParam1,constructorParam2);// this calls the constructor of the class this class extended
}
Here is more detailed info
http://ntt.cc/2009/07/26/beginning-actionscript-3-super-this-setter-getter.html

Sometimes, you have different signatures
package {
public class A {
protected var _a:String, _b:String;
public function A(a:String, b:String) {
_a = a;
_b = b;
}
}
}
package {
public class B extends A {
private var _c:Number;
public function B(c:Number) {
super('', '');
_c = c;
}
}
}
You have to be aware of the different arguments and their meaning. Also, provide useful defaults if possible.
Just some additional input.

Related

How to Override Constants in ActionScript 3

I have the two following classes:
public class Parent{
static internal const _name:String = "Parent";
public function get name():String{
return _name;
}
}
public class Child{
static internal const _name:String = "Child";
}
If I create an instance of class Child and call its name() getter, since it will call the name() method it inherits from Parent, it returns "Parent". I could, of course, override the name() method:
public class Child{
static internal const _name:String = "Child";
override public function get name():String{
return _name;
}
}
That returns "Child". However, it seems silly to have to copy the exact same code of the method from the parent. Is there any simpler way to do this?
I would take a different approach by making the "name" property a requirement for the parent's constructor:
public class Parent
{
static internal var _name : String;
public function Parent(name : String = "Parent") {
_name = name;
}
public function get name() : String {
return _name;
}
}
Child Class:
public class Child extends Parent
{
public function Child() {
super("Child");
}
}
Firstly, you cannot override static methods or properties - they are not inherited, so no override for them.
Secondly, if you declared a constant to be of a complex type, it is not really a constant. I.e. if it is an object, then you can change its keys / values, if it is an array, you can add / remove members and so on.
But the desire to make this functionality more generic is understandable. So, what I'd do:
Have some property outside both parent and child, let say in class X, or package Y. Let it be package Y. So, you'd create a dictionary in package Y, let it be Y.names and in your name getter you'd do:
import Y.names;
. . .
public function get name() {
return names[(this as Object).constructor];
}
your names variable would be:
package Y {
public var names:Dictionary = generateNames();
internal function generateNames():Dictionary {
var result:Dictionary = new Dictionary();
result[ChildClass] = "child";
result[ParentClass] = "parent";
. . .
return result;
}
}
This way it would be sufficient to only implement name getter in super-class, and all inheriting classes will be able to use super-class code as is, no need to change anything. However, this means that some (maybe important) information pertaining to this class will be stored elsewhere (may be difficult to find, this is not the common way people program in AS3).
your implementation of get name should look like this, then the getter is one and each of the new classes needs to have it's own public static var _name defined:
//in the base class
public function get name():String
{
var _sName:String;
if ((this as Object).constructor._name)
{
_sName = (this as Object).constructor._name;
}
else
{
try
{
var o:Object = getSuperClass(this);
while (o)
{
if (o._name)
{
_sName = o._name;
break;
}
o = getSuperClass(o);
}
}
catch (e:*)
{}
}
return _sName;
}
//as found here: http://www.actionscriptdeveloper.co.uk/getting-the-class-of-an-object-in-as3/
public static function getSuperClass(o: Object): Object
{
var n: String = getQualifiedSuperclassName(o);
if (n == null)
return(null);
return getDefinitionByName(n);
}
the static members can be accessed only via class reference which we can get from constructor object, "this" will point to the current class in the inheritance chain so you can call this in parent class and it will point to a Child in a Child class.
[EDIT]
I've modified it so it tests for existance of the public static property _name if not found on "this" instance then in a loop the parent class is checked until one is found - like inheritance:)
I'm using this feature to create clone method: constructor as helper in clone method implementation
best regards
Why don't you store such a constant within a corresponding function instead of declaring an inaccessible constant?
class Parent {
...
public function get name():String { return 'Parent'; }
}
class Child extends Parent {
...
override public function get name():String { return 'Child'; }
}
By the way, if your Parent class is a descendant of DisplayObject, you should be careful with name property, as it's needed sometimes by operating code, e.g. getChildByName().
I have found something that seems to work. Any feedback is greatly appreciated:
public class Parent{
prototype._name = "Parent";
public function get name():String{
return this["_name"];
}
}
public class Child{
prototype._name = "Child";
}

How to access a Class in the default package from a sub package Class in Flash AS3.0

I got error message when trying to access a class in the default package from the class in its sub package. Can any one help me to sort this out.
FYI, my package structure is A -> B. I meant folder 'A' as default package and 'B' as sub package.
Thanks in advance.
Just create a object of Class A, and call class instance method, from its object.
var classAObj:A = new A();
classObj.MethodA();
I think what you're looking for is for class B to extend class A. That would look something like this in your code:
package main
{
class B extends A
{
// Code here...
}
}
Having code inside packages does not in general affect functionality, it's more an organizational tool. (Except for the internal keyword.)
how about private, protected and public ? I could not see any explanation in the other answers so here it is.
class A
{
private var _password:String;
public var username:String;
protected var serverURL:String;
public function login():void
{
// some code
callServerForLogin();
}
protected function callServerForLogin():void
{
// some code
}
}
class B extends A
{
public function B()
{
var parentPassword = super._password;
// FAILS because private and accessible only inside class A
var parentUsername = super.username
// all ok in here, public property
var parentServerURL = super.serverURL;
// all ok, because it is protected
// also we can call super.login(); or super.callServerForLogin();
}
// IMPORTANT we are also allowed to override public and protected functions
override public function login():void
{
super.login();
// we call the parent function to prevent loosing functionality;
Alert.show("Login called from class B");
}
override protected function callServerForLogin():void
{
super.callServerForLogin();
// keep also parent logic
Alert.show("calling protected method from B");
}
}
// ---- Now considering you declare an object of type B you can do the following
var bObj:B = new B();
// access public properties and call public functions from both B and A
bObj.username = "superhero";
bObj.login();
// will get compile error for next lines
bObj.serverURL = "host.port";
bObj.callServerForLogin();

ActionScript3: Inheriting constructor arguments from parents

I'm making a game in action script 3. In it, I have an actor class from which player and enemy classes will be derived. I'm doing this so that unless I need to provide specific AI or fancy behavior (such as for bosses), I can just make a new clip in the library for each enemy without making an actionscript file.
However, I've run into a problem.
Whenever I try to pass arguments to the construction of an enemy (make it spawn with more health), I get error 1136 (Incorrect number of arguments.)
This is because the constructor created automatically at runtime doesn't have the same arguments as it's parent class. Is there any way to get around this without making a class file where I copy and paste the parent constructor function for each of my hundreds of enemies?
Edit
actually rereading your question I think you may be looking for super();
Example
public class Actor{
private var myHelth:uint;
public function Actor(helth:uint = 100){
myHelth = helth; //this will be set to 100 if nothing it passed in or the value passed
}
}
Class that extends Actor:
public class Boss extends Actor{
public function Boss(){
super(200); //passes 200 to Actor;
}
}
If you're trying to pass data into a classes constructor you need to make sure it's accepting arguments.
public class Actor{
private var myHelth:uint;
public function Actor(helth:uint = 100){
myHelth = helth; //this will be set to 100 if nothing it passed in or the value passed
}
}
Then to use
var a:Actor = new Actor(200); //setting health to 200
var b:Actor = new Actor(); //using the default of 100
Make sure your symbols in Flash Pro have appropriate AS linkage, then use pass constructor arguments in super statements:
Actor - base class
package
{
public class Actor
{
public function Actor(name:String, role:String)
{
}
}
}
Player - inherits from Actor defining its own constructor parameters:
package
{
public final class Player extends Actor
{
public function Player(... params:Array)
{
// pass desired inherited constructor parameters
super("name", "role");
}
}
}
Enemy - inherits from Actor defining its own constructor parameters:
package
{
public final class Enemy extends Actor
{
public function Enemy(... params:Array)
{
// pass desired inherited constructor parameters
super("name", "role");
}
}
}

Overriding a public variable with set

I have a base class like this
class Base {
public var space:Number;
}
which gets extended by
class Desc extends Base {
override public function set space( space:Number ):void {
//code
}
}
This doesn't compile. Say, you don't have control of the base class, what ways is there implement the same thing?
The obvious is create a function setSpace(), but this object is being embedded in an already existing system that use the public space.
Thanks in advance.
Your base class should be defined that way:
class Base {
// Don't use public variables. Make them private and define setters and getters
private var space_:Number;
public function get space():Number {
return space_;
}
public function set space(v:Number):void {
if (space_ === v) return;
space_ = v;
}
}
And then it can be overriden that way:
class Desc extends Base {
override public function set space( space:Number ):void {
//code
}
}
Edit:
I missed the part where you say you don't have control over the base class. In that case, hope that space is defined as a getter/setter (it should be if the class is implemented properly). If not, you'll indeed have to use a function such as getSpace and setSpace.
From Adobe:
Class member variables that are declared using the var keyword cannot
be overridden in a subclass.
Using a setter is not an option in your case. If you need to preserve the interface, use composition instead of inheritance:
class Desc {
private var _base:Base;
public function set space(space:Number):void {
//code
this._base.space = space;
}
}

AS3 - References to argument, is that bad?

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.