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.
Related
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";
}
}
}
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.
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();
}
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.
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?