ForumsProgramming ForumAccessing the "Parent Class"

12 3789
IQAndreas
offline
IQAndreas
299 posts
Peasant

I am not talking about the parent in the Display Object Hierarchy (the parent that can be accessed when you write class1.addChild(class2); .

For example, how would class2 here access class1? Or access class1.property1?

public class class1
{

private var class2:class2object = new class2object()

function property1():String
{
return "From property1";
}

}


I want class2 to be able to call property1. Is there any way for it to know its &quotarent"?

I have a bit of a time constraint here, so any help ASAP would really be appreciated.

  • 12 Replies
Erasmus_Darwin
offline
Erasmus_Darwin
59 posts
Nomad

Parent class (or super class) generally refers to inheritance rather than membership. Rather than making a member variable of type class2object within class1, can you just make class2object extend class1?

public class class2object extends class1 {
public function blah():void {
trace(property1()); // Traces "From property1"
}
}

With inheritance, a class2object object always has an associated class1 (since their definitions are intertwined). The problem with the way you've got it is that you could instantiate a class2object somewhere else, and the containing class might not even have a property1() function.

However, if you're set on doing it as a member variable, you can always pass a "this" reference to class2 and save it. "this" always refers to the current object, so within class1, it'd refer to your class1 object. Within the class1 constructor, you could do something like "class2.mycontainingobj = this;" and then your class2object object would have access to the containing object via the mycontainingobj variable.

There may be a better way to do this. I'm not really an AS expert or anything. But these two options should at least put you on the right track.

dank
offline
dank
986 posts
Peasant

What you're talking about is called the super class. When you extend a class, say class2 extends class1, the new class, class2, will inherit all of the super's methods, properties, etc. You don't have to do anything special to call the functions that you wouldn't do otherwise, except if you want to use the code from one of the functions when overriding it, then you can use super.function() to call the super's version of the function.

IQAndreas
offline
IQAndreas
299 posts
Peasant

Sadly, I cannot extend the class, since I will be having more than one class2object in my code, and they all need to access the parent.

Is it possible to make a reference to the parent, such as this?


import com.parentClass;
public class childClass
{

private var _myParentarentClass;

public function childClass(myParentarentClass = null):void
{
_myParent = myParent;
}

public function PrintParent():void
{
if (_myParent != null)
{trace(_myParent.PrintString());}
}

}


import com.childClass;
public class parentClass
{

//Yes, I know I can use an array here.
private var child1:childClass;
private var child2:childClass;
private var child3:childClass;

public function parentClass():void
{
myString = "Hello World!";

//Will doing this pass in a copy of this (a parentClass object), or will it pass in a reference to this?
child1 = new childClass(this);
child2 = new childClass(this);
child3 = new childClass(this);
}

private var myString:String
public function PrintString():String
{
return this.myString;
}

//As a sample, run this function
public function useChildren():void
{
//First, do not change myString
child1.PrintParent();
child2.PrintParent();
child3.PrintParent();

//Then, change the string
//If the printed value also changes, then passing in this as a parameter passes a reference and not a new copy of the class (and vice versa)

myString = "Now printing class1";
child1.PrintParent();

myString = "Now printing class2";
child2.PrintParent();

myString = "Now printing class3 - Just because I can.";
child3.PrintParent();
}

}


I just realized that instead of just asking if the code works, I will try it out. (Duh...)

The problem with the way you've got it is that you could instantiate a class2object somewhere else, and the containing class might not even have a property1() function.

And that is probably why you are unable to access the parent directly.
IQAndreas
offline
IQAndreas
299 posts
Peasant

Wohoo! It worked.

Here is the output (as expected):


Thanks for the help... sortof...

Now how do you pass in a copy of this without having to create a function that sets all of the &quotarent object's" properties manually. The problem with doing that manually is that you have to update the function every time you add a new property to an object.

In VB.net this is so much easier. All you do is use ByVal (Sends a copy, or only the values of the object) or ByRef (Sends a reference). Is there anything like this for Flash?

IQAndreas
offline
IQAndreas
299 posts
Peasant

Oops. Forgot the output. (I wish we could edit our posts)

Hello World!
Hello World!
Hello World!
Now printing class1
Now printing class2
Now printing class3 - Just because I can.
Erasmus_Darwin
offline
Erasmus_Darwin
59 posts
Nomad

IqAndreas wrote:

Now how do you pass in a copy of this without having to create a function that sets all of the &quotarent object's" properties manually. The problem with doing that manually is that you have to update the function every time you add a new property to an object.


Objects in ActionScript are just associative arrays: (doc page)

So you can write a function to enumerate through the properties of the object and set them in another object: (example from that same doc page)

The meat of the example is basically this bit:
public function Circle(initObj:Object) {
for(var i:String in initObj) {
this[i] = initObj[i];
}
}

However, this isn't a deep copy. If initObj contains a reference to another object, then the copy will also receive a reference to that object rather than its own copy. If that's the case, then you'd need to recursively copy each object referenced by the other object.
dank
offline
dank
986 posts
Peasant

I don't see why you need to bother with passing the reference to the child as the child already has the property 'arent' which is a reference back to parentClass. Thus '_myParent' and 'arent' hold the same reference and is adding unneeded complexity to your code.

Erasmus_Darwin
offline
Erasmus_Darwin
59 posts
Nomad

Dank, &quotarent" only works for DisplayObject-related addChild relationship which IqAndreas said way back at the start that he wasn't interested in.

IQAndreas
offline
IQAndreas
299 posts
Peasant

So you can write a function to enumerate through the properties of the object and set them in another object

I thought you could only enumerate through the properties of dynamic classes. I read that recently... I think. I need to double check.

Yes. I believe that I am correct. The only reason that code works is because initObject is a dynamic class:
var secondInitObj:Object = {bgColor:0xCCCCCC, radius:50, xCenter:50, yCenter:50};


Non-dynamic classes (which is different than static classes) run much faster and take up less memory because they are stored differently.

But thanks for the link. Now I know how to get ahold of Flash Help when online (which I only am about 30% of the time, but still good to know).
Erasmus_Darwin
offline
Erasmus_Darwin
59 posts
Nomad

I found a way to enumerate a sealed class (that's apparently the official term for non-dynamic classes). I'm not sure why it works, but it looks like it does.

Anyway, I started with the "ByteArray for deep copies of objects" tip from Senocular. The problem with that is that it produces a result that's just of type Object. I couldn't find a way to coerce the Object back to its propery class type.

However, I discovered something weird. I could enumerate through the fields of the clone just fine. Furthermore, I could reference the properties in the sealed class via the [] operator as long as I knew the property names by enumerating the fields of the clone.

Anyway, here's some sample code:
var sprite:Sprite = new Sprite();

var clone:Object;
var copier:ByteArray = new ByteArray();
copier.writeObject(sprite);
copier.position = 0;
clone = copier.readObject();

var i:String;

trace("Enumerating sprite:"

for (i in sprite) {
trace(i, "=", sprite[i]);
}

trace("Enumerating sprite via clone:"

for (i in clone) {
trace(i, "=", sprite[i]);
}

I threw that in my main class, and the direct enumeration of sprite fails as expected while the enumeration via clone reveals all the values within sprite. For a copy of the proper class type, you could presumably use the enumeration loop to copy the individual values from sprite (for a shallow copy) or clone (for a deep copy) to a new sprite object. Although I supposed the Sprite class isn't the best example since Sprite.graphics is read-only.

IQAndreas
offline
IQAndreas
299 posts
Peasant

Excellent, Erasmus_Darwin. This will really come in handy.

I extended the code even further, so now it is all in one little function AND you can see all the properties of all the objects nested in the objects.

function ListContents(obj:Object, Indent:String = "&quot:void
{

var clone:Object;
var copier:ByteArray = new ByteArray();
copier.writeObject(obj);
copier.position = 0;
clone = copier.readObject();

for (var i:String in clone)
{
trace(Indent + i + " = " + obj[i]);
if (obj[i] is Object)
{ ListContents(obj[i], Indent + " " }
}

}


And to try this out:
import flash.text.TextField;

var tf:TextField = new TextField();
tf.text = "Hello world!";

ListContents(tf);


Which results in:
tabEnabled = false
scale9Grid = null
name = instance1
mouseEnabled = true
rotationX = 0
scrollH = 0
borderColor = 0
scaleZ = 1
condenseWhite = false
blendMode = normal
textColor = 0
doubleClickEnabled = false
multiline = false
contextMenu = null
scrollRect = null
tabIndex = -1
htmlText = <P ALIGN="LEFT"><FONT FACE="Times New Roman" SIZE="12" COLOR="#000000" LETTERSPACING="0" KERNING="0">Hello world!</FONT></P>
accessibilityProperties = null
styleSheet = null
defaultTextFormat = [object TextFormat]
color = 0
display = block
blockIndent = 0
bullet = false
bold = false
size = 12
italic = false
tabStops =
font = Times New Roman
leading = 0
target =
kerning = false
url =
indent = 0
align = left
letterSpacing = 0
rightMargin = 0
leftMargin = 0
underline = false
rotationY = 0
rotationZ = 0
opaqueBackground = null
autoSize = none
y = 0
x = 0
alpha = 1
height = 100
visible = true
backgroundColor = 16777215
embedFonts = false
cacheAsBitmap = false
border = false
z = 0
type = dynamic
antiAliasType = normal
maxChars = 0
scrollV = 1
thickness = 0
background = false
scaleY = 1
scaleX = 1
alwaysShowSelection = false
sharpness = 0
displayAsPassword = false
selectable = true
mouseWheelEnabled = true
width = 100
mask = null
wordWrap = false
rotation = 0
accessibilityImplementation = null
gridFitType = pixel
transform = [object Transform]
colorTransform = (redMultiplier=1, greenMultiplier=1, blueMultiplier=1, alphaMultiplier=1, redOffset=0, greenOffset=0, blueOffset=0, alphaOffset=0)
color = 0
alphaOffset = 0
redOffset = 0
greenMultiplier = 1
blueMultiplier = 1
greenOffset = 0
blueOffset = 0
alphaMultiplier = 1
redMultiplier = 1
matrix3D = null
perspectiveProjection = null
matrix = (a=1, b=0, c=0, d=1, tx=0, ty=0)
b = 0
tx = 0
d = 1
a = 1
ty = 0
c = 0
text = Hello world!
focusRect = null
restrict = null
useRichTextClipboard = false
filters =
Erasmus_Darwin
offline
Erasmus_Darwin
59 posts
Nomad

IqAndreas wrote:

I extended the code even further, so now it is all in one little function AND you can see all the properties of all the objects nested in the objects.


Nice! Data:umper is one of my favorite debugging modules in Perl, so it's nice to have an equivalent for AS3.
Showing 1-12 of 12