"Access of undefined property" errors when the property is actually defined - actionscript-3

Answered my own question: I can't declare any variables out in the open like that in my class. They have to be declared in a function, in this case, initialize();
I have a class called "Sushi"
package {
public class Sushi {
private var cName: String; // This is the name of the sushi.
private var cBio: String; // This is the description of the sushi.
private var cWeight: Number; // This is the weight modifier of the sushi (please keep it between 0.1 and 2.0).
//public var cSprite: MovieClip; // This is the sushi's graphic.
private var cResist: Number; // This is the sushi's resistance modifier.
public function setName(n:String): void {
cName = n;
}
public function setBio(b:String): void {
cBio = b;
}
public function setWeight(w:Number): void {
cWeight = w;
}
public function setResist(r:Number): void {
cResist = r;
}
public function getName(): String {
return cName;
}
public function setCurrentChar(): void {
MainClass.curChar = this;
}
}
}
...and a main class. My main class creates two Sushi objects: test1 and test2.
private var test1 = new Sushi();
test1.setName("Test1");
private var test2 = new Sushi();
test2.setName("Test2");
Whenever I run it, I get the errors "Access of undefined property test1" and the same for test2. What am I doing wrong and how can I learn from my mistake?

Because you declared your members as private, they are not accessible outside the scope of the class.
In classes there are access modifiers which control scope. For example:
internal — visible to references inside the same package
private — visible to references in the same class
protected — visible to references in the same class and derived classes
public — visible to references everywhere
static — specifies that a property belongs to the class, as opposed to instances of the class
In your example Sushi class, because you declared those members as private they can only be seen by the Sushi class.
package {
public class Sushi {
private var cName:String;
public function setName(n:String): void {
cName = n;
}
}
}
However, you could declare the member as public:
package {
public class Sushi {
public var cName:String;
}
}
When declared as public, you can now access them like:
var sushi:Sushi = new Sushi();
suschi.name = "Kappa Maki";
Your workaround is what's regarded as a property, in which a getter and setter are defined for a variable.
For example, here _price is property only the Sushi class has access to; however, it exposes two public methods to get or set the price value:
package {
public class Sushi {
private var _price:Number;
public function get price():Number {
return _price;
}
public function set price(value:Number):void {
_price = value;
}
}
}
This object-oriented programming concept is known as encapsulation, and helps to hide internal complexities of your class.
By removing the setter, you can create a read-only property:
package {
public class Sushi {
private var _price:Number = 7.99;
public function get price():Number {
return _price;
}
}
}
Now, you can retrieve get the price; however, you cannot set it.
var sushi:Sushi = new Sushi();
trace("price is: $" + sushi.price); // traces: price is: $7.99
If you try to set the property, your compiler will throw an error:
var sushi:Sushi = new Sushi();
sushi.price = 1.99; // throws error: Property price is read-only.
Per their initialization, you can set their default value inline to their definition, as in:
package {
public class Sushi {
public var cName:String = "Kappa Maki";
}
}
Alternatively, you can set their initial values in the class constructor which is executed when you declare a new instance:
package {
public class Sushi {
public var cName:String;
public function Sushi {
cName = "Kappa Maki";
}
}
}

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.

How to access a public array/vector from another class

I have a vector in my Main class file that store objects. I will like to be able to add more objects to that SAME vector from a different class. I gave the vector in my main class the "public" modifier. I now need the syntax to reference it in my other class file
public var badChar:Vector.;
You have options. How you approach it is dependent on your project setup, and the needs of the property. Is it an instantiated object, or should there ever only be one (even if the class is instantiated multiple times)? Do you need direct access to it regardless of any relationship to the stage? Each solution below has pros and cons.
Class-to-Class via Stage
Assuming the following main foo.as class:
package {
public class Foo {
public var bool:Boolean = true;
}
}
Bar class:
package {
public class Bar extends Sprite {
import flash.events.Event;
public function Bar() {
addEventListener(Event.ADDED_TO_STAGE, accessFoo);
}
private function accessFoo(e:Event):void {
trace(this.parent["f"].bool); // traces "true"
}
}
}
Document Code:
var f:Foo = new Foo();
var b:Bar = new Bar();
addChild(b);
Inheritance
Foo Class:
package {
public class Foo {
public var bool:Boolean = true;
}
}
Bar Class
package {
public class Bar extends Foo {
public function Bar() {
trace(bool); // traces "true"
}
}
}
Class-to-Class via Static
Some disclaimers should be in order for Static properties, but I'll leave you to read up on those.
Foo Class:
package {
public class Foo {
public static var bool:Boolean = true;
}
}
Bar Class
package {
public class Bar {
public function Bar() {
trace(Foo.bool); // traces "true"
}
}
}
Direct Access via New Declaration
Foo Class:
package {
public class Foo {
public var bool:Boolean = true;
}
}
Bar Class
package {
public class Bar {
import Foo;
public function Bar() {
trace(new Foo().bool); // traces "true"
}
}
}
Access via Sharing
Foo Class:
package {
public class Foo {
public var bool:Boolean = true;
}
}
Bar Class
package {
public class Bar {
import Foo;
public var fluffy:Foo;
public function Bar() {
trace(fluffy.bool);
}
}
}
Document Code:
var f:Foo = new Foo();
var b:Bar = new Bar();
b.fluffy = f;
Note that after the third line in the document code, fluffy is no longer an undeclared variable and will now point to the f object, where the properties updated in it (such as bool) will reflect inside of Bar.

AS3: Type was not found or was not a compile-time constant

I'm having an issue with a little app I'm trying to create at the moment, it's my first try and dealing with classes but for some reason I can't create any instances of the class even if it's imported into the document. Here's the code for the class (named "Players"):
package
{
public class Player
{
public function Player(name_:String)
{
}
public var name_:String;
private var alignment:int;
public var healed:Boolean = false;
public var revealed:Boolean = false;
public var attacked:Boolean = false;
public var dead:Boolean = false;
public function action(target:Player)
{
}
public function describe():String
{
}
}
public class Citizen extends Player
{
public function Citizen(name_:String)
{
alignment = 1;
}
override public function action(target:Player)
{
}
override public function describe():String
{
return "Citizen";
}
}
public class Investigator extends Player
{
public function Investigator(name_:String)
{
alignment = 1;
}
override public function action(target:Player)
{
target.revealed = true;
}
override public function describe():String
{
return "Cop";
}
}
public class Doctor extends Player
{
public function Doctor(name_:String)
{
alignment = 1;
}
override public function action(target:Player)
{
target.healed = true;
}
override public function describe():String
{
return "Doctor";
}
}
public class Mafioso extends Player
{
public function Mafioso(name_:String)
{
alignment = -1;
}
override public function action(target:Player)
{
target.attacked = true;
}
override public function describe():String
{
return "Mafia";
}
}
}
And the code which creates the instance:
import Players;
stop();
var totalplayers:Number;
var playerArray:Array = new Array();
var playerType:Array = ["Citizen","Cop","Doctor","Mafia"];
var test:Citizen = new Citizen("James");
Both are in the same folder. I get the error code 1046 described in the title but I honestly have no idea why, flash picks it up in the code hints yet it comes up with that! Any help would be appreciated.
Also secondary question, I'll never initiate the Player class (except through inheritance with the other classes), so can I make it private?
Thanks
I'm assuming all that code is in a file called Players.as.
This is wrong. Each file should contain one class and the class should be the same name as the .as file.
You currently have two classes (Player and Citizen) within one file.
What you need to do is take the Player class you've defined and place it in its own .as. file with the same name (Player). Do the same for Citizen.
Then you can use:
import Player;
import Citizen;
Though this won't be necessary because you don't need to import classes that are in the same directory that you're trying to access it from.
As for the error, you're getting that because Flash is trying to find the class Players and you don't have a class with that name (just a file with that name).
Per your secondary question regarding whether ActionScript supports private classes, if you have a class that would not otherwise be accessed except internally by a public class you may define it as internal.
Internal classes are visible to references inside the current package.
If you do not want a class to be publicly visible outside a package, place the class inside a package and mark the class with the internal attribute. Alternatively, you can omit both the internal and public attributes, and the compiler automatically adds the internal attribute for you. You can also define a class to only be visible inside the source file in which it is defined. Place the class at the bottom of your source file, below the closing curly bracket of the package definition.
In the following example, both X and Y classes are defined in a single file (X.as). X may be referenced and instantiated as normal; however, Y is internal to X and only visible from from the scope of X.
package
{
import flash.display.Sprite;
public class X extends Sprite
{
public function X()
{
super();
var y:Y = new Y();
}
}
}
internal class Y
{
public function Y()
{
trace("internal Y ctor.");
}
}
This pattern is helpful when a class requires small data models that would not otherwise be accessed outside of a class.
Agree with others here should be as shown below (note filenames match class names, file names are denoted in brackets above code blocks). Also you wrote import Players instead of import Player, regardless as the other poster wrote if all classes are currently in the default package the import is unnecessary.
[Player.as]
package
{
public class Player
{
public function Player(name_:String)
{
}
public var name_:String;
private var alignment:int;
public var healed:Boolean = false;
public var revealed:Boolean = false;
public var attacked:Boolean = false;
public var dead:Boolean = false;
public function action(target:Player)
{
}
public function describe():String
{
}
}
}
[Citizen.as]
package
{
public class Citizen extends Player
{
public function Citizen(name_:String)
{
alignment = 1;
}
override public function action(target:Player)
{
}
override public function describe():String
{
return "Citizen";
}
}
}
[Investigator.as]
package
{
public class Investigator extends Player
{
public function Investigator(name_:String)
{
alignment = 1;
}
override public function action(target:Player)
{
target.revealed = true;
}
override public function describe():String
{
return "Cop";
}
}
}
[Doctor.as]
package
{
public class Doctor extends Player
{
public function Doctor(name_:String)
{
alignment = 1;
}
override public function action(target:Player)
{
target.healed = true;
}
override public function describe():String
{
return "Doctor";
}
}
}
[Mafioso.as]
package
{
public class Mafioso extends Player
{
public function Mafioso(name_:String)
{
alignment = -1;
}
override public function action(target:Player)
{
target.attacked = true;
}
override public function describe():String
{
return "Mafia";
}
}
}
It's unfortunate there's no abstract classes as this would be an ideal situation for an abstract class and abstract methods.

AS3 1120 Error on instantiating

I am trying to create a basic functionality in AS3.
I have a class like this:
package tax
{
public class Calculator
{
public function Calculator()
{
}
private var grwage:Number;
private var taxes:Number;
private var superannuation:Number;
private var insurance:Number;
private var net:Number;
public function getGrwage():Number {
return grwage;
}
public function setGrwage(grwage:Number):void {
this.grwage = grwage;
}
public function getTaxes():Number {
return grwage;
}
public function setTaxes(taxes:Number):void {
this.taxes = grwage * 0.2;
}
public function getSup():Number {
return superannuation;
}
public function setSup(superannuation:Number):void {
this.superannuation = superannuation * 0.05;
}
public function getIns():Number {
return insurance;
}
public function setIns(insurance:Number):void {
this.insurance = insurance * 0.1;
}
public function getNet():Number {
return net;
}
public function setNet(net:Number):void {
this.net = grwage - taxes - superannuation - insurance;
}
}
}
Just some getters and setters.
And in my mxml file:
import tax.Calculator;
public var calculate:Calculator = new Calculator();
calculate.setGrwage(1000);
trace(calculate.getTaxes());
trace(calculate.getSup());
trace(calculate.getIns());
trace(calculate.getNet());
I get an error 1120 Access to undefinded property when I try to access calculate. Do you have any ideas?
Thanks.
I guess you're mixing up things a bit between getters and setters. If a variable depends on another, you have to write the calculation in its getter. This variable shouldn't exist as a private member and the accesses to it must always be done through the appropriate getter.
for example:
public function getNet():Number {
return getGrwage() - getTaxes() - getSup() - getIns();
}
So here, you only need one setter (setGrwage), you can remove the others ones and put the calculation in the getters.
Note that there is a more appropriate syntax for setters and getters in AS3.
class GetSet
{
private var privateProperty:String;
public function get publicAccess():String
{
return privateProperty;
}
public function set publicAccess(setValue:String):void
{
privateProperty = setValue;
}
}
There are multiple issues with your class. So lets redesign it
The main issue you had was you were not initiating the vars before you accessed them as they had a NULL value the flash player was throwing you that error.
As you can see in the constructor I set a default value of 0 so that they will never be NULL.
package tax {
public class Calculator{
private var _grwage:Number;
private var _taxes:Number;
private var _superannuation:Number;
private var _insurance:Number;
public function Calculator() {
this._grwage = 0;
this._taxes = 0;
this._superannuation = 0;
this._insurance = 0;
}
public function get grwage():Number {
return this._grwage;
}
public function set grwage(val:Number):void {
this._grwage = val;
}
public function get taxes():Number {
return this._taxes;
}
public function set taxes(val:Number):void {
this._taxes = val * 0.2;
}
public function get superannuation():Number {
return this._superannuation;
}
public function set superannuation(val:Number):void {
this._superannuation = val * 0.05;
}
public function get insurance():Number {
return this._insurance;
}
public function set insurance(val:Number):void {
this._insurance = val* 0.1;
}
public function get net():Number {
return this._grwage - this._taxes - this._superannuation - this._insurance;
}
}
}
import tax.Calculator;
public var calculate:Calculator = new Calculator();
//Now due to the fact we are using true setter/getter methods.
calculate.grwage = 1000;
trace( calculate.taxes); // should be 0 as we are defaulting to the initial value
trace( calculate.superannuation );// should be 0 as we are defaulting to the initial value
trace( calculate.insurance );// should be 0 as we are defaulting to the initial value
trace( calculate.net );// should be 1000 as we are defaulting to the initial values of everything but grwage
The answers here are all good, but they all miss the primary point:
You're trying to get your variables before you set them.
import tax.Calculator;
public var calculate:Calculator = new Calculator();
calculate.setGrwage(1000);
trace(calculate.getTaxes());
trace(calculate.getSup());
trace(calculate.getIns());
trace(calculate.getNet());
This will throw an error (due to the way you've set up your class), because you never called setSup(), setIns(), and setNet() before trying to use them.
While your class may not be written in the best way, it is syntactically sound.
Try calling each setter before your getter. I think you'll solve your issue.

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?