A Flash Developer Resource Site

Results 1 to 18 of 18

Thread: Instances are just copies right?

  1. #1
    thinking is design retrotron's Avatar
    Join Date
    Apr 2003
    Location
    Utah
    Posts
    141

    Instances are just copies right?

    I posted this on ultrashock too, but I might get a quicker reply here. Two questions.

    First question: in actionscript, there isn't such a thing as a "class". Instead, the "class" is just an object, and when you create new instances of the class, you are actually just creating copies of that object. Am I understanding this right?

    Second question: if so, then how does prorotype work? Wouldn't that mean that there is a separate prototype for every "copy"? How then does prototype work? Does Flash just automatically copy onto all instance's prototype anything that is declared on the master object's prototype (i.e. thisInstance.prototype is an exact copy of the masterObject.prototype)? Or perhaps do all instance's just get an object reference (i.e. thisInstance.prototype is a reference to mainObject.prototype rather than a copy of masterObject.prototype)?

    absconditus.com // experiments in actionscripted design

    "I really must get a thinner pencil. I ca'n't manage this one a bit: it writes all manner of things that I don't intend". // Alice, Through the Looking Glass

  2. #2
    half as fun, double the price senocular's Avatar
    Join Date
    Feb 2002
    Location
    San Francisco, CA (USA)
    Posts
    4,361
    Instances arent copies, their.. umm... 'die-casts' from a mold (the class). To make a die-cast, metal is poured into a die (the mold) and cooled to form your final metalic object. The mold itself is not the same object but rather something which dictates what the final object should be; how big it is, its shape, etc.

    In Flash the die, or mold, is a Class function. The die-cast is your object instance. The class function, aka class constructor, is what is used to define your object instance. It tells what properies the instance is to have and can even set functions for that instance - all things which are specific to that one instance. So, if you make multiple instances from this constructor, they will (typically) all have the same properties, since, afterall, you are using the same mold to make them.

    constructorFunction = function(){
    // ...
    }

    In Flash, whenever a function is defined within a timeline, Flash also creates with that function a companion object called a prototype. This is an object that is used for object instances created by that function if it is used as a class constructor. If the function is NOT used as a constructor, then the prototype just sits there with no purpose. Flash has no way of determining whether or not your function is going to be a constructor or not, so it will make a prototype in any case.

    constructorFunction.prototype;

    Instances are created from a function using the 'new' keyword. When new is put before a function in Flash, Flash runs that function as a constructor function as opposed to a 'normal' function. The difference is, as a constructor function, the 'this' keyword will reference the new object instance being created rather than the scope the function exists, as it would be normally. Constructor functions also automatically return a reference to the new object created - this object being an object defined by that constructor function run setting properties and whathaveyou within that function itself.

    myInstance = new constructorFunction();

    When a new object is created in this manner it gets 3 properties set for it under your nose, __proto__, constructor, and __constructor__. These play a role in how your object reacts and what it references when looking for methods and properties etc. when they dont exist in the object itself

    __proto__ is a reference to the constructor functions prototype object - that companion object automatically created along with that function's definition. __proto__ is a kind of 'next in line' sign that tells an object where to go looking next if you request a property or method that doesnt exist within that object instance itself.

    myInstance.__proto__;

    For instance, lets say you were looking for a picture you have of you at 5 years old blowing out candles at your birthday party and you know its in one of your many photo albums. First you'd search through your first photo album. When you don't find it there, you move on to the next one to look for it there. You keep doing this until you find the picture.

    __proto__ is to Flash, a reference to that next photo album. Every object has one telling it where to look next if you attempt to access a property or method that doesnt exist within that instance itself. For normal objects, the __proto__ references the Object.prototype since objects themseleves are... objects. When you create an instance with a constructor function, it sets the new instance's __proto__ to be that function's prototype object.

    myInstance.__proto__ == constructorFunction.prototype;
    myObj = {}
    myObj.__proto__ == Object.prototype;

    With this reference, it gives you can common place or library to store methods and properties for all instances from a particular constructor function since they will all search the constructor function's prototype if the instance itself doesnt doesnt have whats requested. Heres a simple example:

    Code:
    Class = function(){
    	this.methA = function(){
    		trace("methA in object instance");
    	}
    }
    Class.prototype.methA = function(){
    	trace("methA in class prototype");
    }
    Class.prototype.methB = function(){
    	trace("methB in class prototype");
    }
    
    myInstance= new Class();
    trace(myInstance.__proto__ == Class.prototype); // true
    myInstance.methA(); // methA in object instance
    myInstance.methB(); // methB in class prototype
    so here, mehtA and methB are both in the prototype of the class, but methA is also defined to be in the instance created from the Class constructor function. When you call anything from the instance itself, the instance first checks to see if it has its own property or method of whatever was requested, if not it checks its __proto__ to see where it should look next. Since we created the myInstance above from the Class function, its __proto__ references Class's prototype object. This tells myInstance to look there when it cant find its own requested property or method. In the example above, we 'requested' methA and methB from the created myInstance. myInstance has its own methA so thats what was run when called. There was no need for the __proto__ to be used since methA already existed within that instance. methB however, does not exist within that instance. In that case, myInstance first searches its own object contents for methB; when not found, it then accessed its __proto__, saw that it pointed to Class.prototype and then looked there for methB where it found it and ran the trace.

    Something else to remember about prototypes is that they are, themselves, just objects. There is nothing fundamentally special about the prototype objects. They're just objects created for each of your functions. As objects, though, as with all objects, they contain a __proto__ reference. Initially, this reference is pointing to the Object.prototype since the prototype is just an object. Because of this, any prototype also has its own 'where to look' object if it cant a request within itself. This develops a __proto__ chain where in the case of myinstance, it first looks in its own object contents, then references __proto__ to look in Class.prototype, which can then, reference THAT __proto__ and look into Object.prototype.

    That is Flash inheritance. You have one object which not only has its own properties and methods, but also have a reference (__proto__) to access other properties and methods within other objects, namely prototype objects. This inheritance chain for normal constructor class instances stretches across 3object scopes counting the instances own:

    instance
    |
    (__proto__ points to)
    V
    instance constructor prototype
    |
    (__proto__ points to)
    V
    prototype constructor prototype (which is object.prototype)

    However, you can extend this chain to be longer by changing the __proto__ of a prototype to be another object - prefereably another prototype object which contains properties and methods of another Class. This is done by setting the prototype of a constructor to be a new instance of another Class.

    As an basic object, a prototype of a class is an empty shell of nothing asside from a __proto__ which references the Object prototype. If you set a prototype to be a new object instance, such as one created from another class constructor, it will then have a __proto__ pointing to that class's prototype which itself may or may not be pointing to another prototype object finally leading down to the object.prototype - all with a chaing of __proto__ references which given an instance of the last class in the chain will go through each one of those classes looking for a method to run for it when called. Ex:

    Code:
    ClassA = function(){}
    ClassB = function(){}
    ClassB.prototype = new ClassA();
    myInstance = new ClassB();
    
    myInstance.__proto__ == ClassB.prototype;
    ClassB.prototype.__proto__ == ClassA.prototype;
    ClassA.prototype.__proto__ == Object.prototype;
    Just as ClassB.prototype was any other kind of instance, its __proto__ references ClassA.prototype when its set to be a new ClassA.prototype. Afterall, it is basically just an Object instance to begin with. Making it an instance of ClassA just makes it an object instance with a different __proto__. If you're familiar with Flash % inheritance, then you've seen the use of inheritance just by altering this __proto__ reference. Its not standard now, but still effective and can be desirable given different situations.

    constructor and __constructor__. These are the other 2 protperties given to object instances. These. as you might have guessed, reference the class constructor function used to create the instance. This also means for any instance, its __proto__ is the same as its constructor.prototype:

    myInstance.__proto__ == myInstance.constructor.prototype;

    Technically, you're allowed to know constructor exists, but __constructor__ is the hidden guy. He is actually used in making super() effective. constructor (no underscores) is just there for kicks. You can alter and change constructor without any real residual repercussions, but altering __constructor__ will break your super object.

    ... for more on supper, look in Ultrashocks Actionscript forum and actionscript.org's Flash MX forums. I have a couple of posts there which go into more detail about super. Actually the as.org post is pretty good. Heres a link http://www.actionscript.org/forums/s...threadid=28710 (though youve probably already seen it retrotron)


  3. #3
    thinking is design retrotron's Avatar
    Join Date
    Apr 2003
    Location
    Utah
    Posts
    141
    Gee, thanks for giving me the time senocular! You're the best! I learned a lot from this (and I know others will too). You've really helped clarify a lot of things. It especially helped me clarify just what prototype and __proto__ are objects references to. Funny how it seems so simple once you get it, but before you get it seems so hazy.

    Okay, so I've got one more question. I've heard that Flash doesn't really have such a thing as a true class. When we create a "class" in Flash, it isn't really a class. When all the disguises are off, the "class" in Flash is really just an object. Is that right? If so, then let me see if I understand how Flash works (in particular how it can simulate OOP without a true class).

    When you create a function, prototype, __proto__, constructor, and __constructor__ are created along with it. prototype is just an empty object whose __proto__ is an object reference to Object.prototype. That is function.prototype's __proto__. function.__proto__ , however, is an object reference to function.prototype. Okay, I got the inheritance chain. At least I do if what I just said is right.

    Now, when you create an instance, Flash creates an object whose __proto__ is an object reference to the constructor function's prototype object. Thus, when I declare methods on the constructor function's prototype object, all those objects who have a __proto__ pointing to said prototype object will inherit that prototype object's methods.

    Okay, now that I have all that straightened up, I can ask my original question so much better (and I actually understand my original question, I sure didn't before ). In Flash, the "class" is just an object, not a true class (after all, a true class doesn't really "exist", but Flash's classes do "exist", they are objects). All "instances" of said class are also just objects who merely inheret the methods of the class's prototype object via the instance's __proto__ object reference (which is a pointer to the class's prototype). So really, what we have is one "master" object (which we call a "class"), the initial function to whose prototype object all methods are attached. Then we have a bunch of other objects (which we call "instances") who merely inherit the "master" object's prototype object methods. I was trying to call these other objects "copies" earlier, but that's not quite accurate. Their just objects who inherit a particular prototypes methods, and it is this inheritance which makes them "instances" of a particular constructor function rather than another (althought with inheritance we can tweak where __proto__ points).

    This is different from hardcore OOP languages such as Java where a class is truly a class, not an object. A class actually doesn't "exist" in Java, it's simply a set of instructions/blueprints/mold for instances/objects which will indeed "exist" once instantiated. So what I'm getting at is that Flash simulates a "class" by creating an object and then pointing all "instance" objects to its own prototype.

    Is that how it works?

    On a slightly related note . . . I know nothing about Java or C++, but do they run inheritance anything like Flash, or is this whole "prototype chain" something that MX cooked up in order to simulate the whole class-instance thing?

    Btw, yeah, I've seen that as.org post, it makes more and more sense everyday. Actually, it makes a LOT of sense now, thanks to you.

    absconditus.com // experiments in actionscripted design

    "I really must get a thinner pencil. I ca'n't manage this one a bit: it writes all manner of things that I don't intend". // Alice, Through the Looking Glass

  4. #4
    half as fun, double the price senocular's Avatar
    Join Date
    Feb 2002
    Location
    San Francisco, CA (USA)
    Posts
    4,361
    "In Flash, the "class" is just an object, not a true class (after all, a true class doesn't really "exist", but Flash's classes do "exist", they are objects)."

    I reluctantly flinch each time you say the Class is an object. Its really a function. I say reluctantly because a function itself is an object in flash, but its not like an object object, its a function object. Consider the following:
    Code:
    myFunctionObj = function(){
    	this.prop1 = 1;
    	this.prop2 = 2;
    };
    myObjectObj = {
    	prop1: 1,
    	prop2: 2
    };
    myFunction does not contain prop1 or prop2 like myObjectObj does. If you try to access either in myFunctionObj, you'll get undefined, while in myObjectObj, they're their respective values:
    Code:
    trace(myFunctionObj.prop1); // undefined
    trace(myFunctionObj.prop2); // undefined
    trace(myObjectObj.prop1); // 1
    trace(myObjectObj.prop2); // 2
    myFunction is, instead, a function that, when called, assigns to an object designated by 'this'. If myFunction is called normally, this will reference the timeline

    myFunctionObj();

    but if used with new, this reference a new object instance created by that function as a constructor... which technically, no, is not a 'real' class so much as just a function used to define a class. The function still exists as a function at runtime and behaves just like any other function does unless used with new. Then it becomes a class constructor and develops a new instance of itself - though 'of itself' is not making a copy of that function at all, rather making an object object with properties set within the code of that function (like prop1 and prop2 in the example above) whos __proto__ is set by that function to reference its that function's prototype and whos constructor and __constructor__ references that function itself.

    "When you create a function, prototype, __proto__, constructor, and __constructor__ are created along with it."

    Eh...

    Ok, there is a __proto__ and constructor (no __constructor__) within the function when its created because a function IS an object. A function's __proto__ references Function.prototype and its constructor is the Function object - a function is an instance of Function. Note, however, these function __proto__ and constructor properties have absolutely nothing to do with instances created from that function when its run as a constructor. These are the functions own __proto__ and constructor where __proto__, constructor, and __constructor__ are created seperately for each instance created by that function for that instance to reference that function constructor.

    But yeah, I think you got it down for the most part. Inheritance through Flash is run through the __proto__. You technically dont need class constructor functions if you just set __proto__ yourself. Simple ex:
    Code:
    pseudoSuperClass = {};
    pseudoSuperClass.superprop = "set superprop value";
    
    pseudoSubClass = {};
    pseudoSubClass.__proto__ = pseudoSuperClass;
    
    pseudoSubClass.subprop = "set subprop value";
    
    pseudoInstance = {}
    pseudoInstance.__proto__ = pseudoSubClass;
    pseudoInstance.prop = "set prop value";
    
    trace(pseudoInstance.prop); // set prop value
    trace(pseudoInstance.subprop); // set subprop value
    trace(pseudoInstance.superprop); // set superprop value
    In terms of inheritance with Flash compared to C++ and Java... yeah, its not quite the same. Flash has no private properties and is just setup slightly different. Its really closer to Javascript. I wish I could remember more about C++ to give a better explanation in the differences (my Java knowledge has never been that developed) but its been so long since Ive used it and Ive been so engrossed in Flash lately that its probably gone forever; replaced with Flash junk like this ^



  5. #5
    thinking is design retrotron's Avatar
    Join Date
    Apr 2003
    Location
    Utah
    Posts
    141
    Okay, I'm totally tracking with you, or at least I think I am. You must forgive my semi-incoherent ramblings. After 24 hours without sleep I just turn into a bumbler (whatever that is). I actually start to think that I'm funny, and a real ninja. I'm going to bed soon and my communication should get better after that.

    I finally tracked down the reference in the back of my mind which was behind all this: ECMA-262 docs say such scripts are not "class-based", rather they are "object-based" or "prototype-based". I was trying to figure out how actionscript actually works if the class isn't really a "class". Thanks to your excellent explanation I now understand how all this works.

    And I think I see what you're saying about the object/function stuff, since Flash "objects" are really built on functions which have been "enhanced" via the prototype chain. Uh . . . hopefully that's right.

    absconditus.com // experiments in actionscripted design

    "I really must get a thinner pencil. I ca'n't manage this one a bit: it writes all manner of things that I don't intend". // Alice, Through the Looking Glass

  6. #6
    half as fun, double the price senocular's Avatar
    Join Date
    Feb 2002
    Location
    San Francisco, CA (USA)
    Posts
    4,361
    you got it

  7. #7
    thinking is design retrotron's Avatar
    Join Date
    Apr 2003
    Location
    Utah
    Posts
    141
    Here is some relevant reading for anybody following this thread, courtesy of ultrashock's x3ro.

    http://www.webreference.com/js/tips/010215.html
    http://www.laputan.org/reflection/warfare.html
    http://www.cs.vu.nl/~eliens/online/o...prototype.html

    Thanks again senocular, you've been a great help. A light bulb turned on thanks to you.

    absconditus.com // experiments in actionscripted design

    "I really must get a thinner pencil. I ca'n't manage this one a bit: it writes all manner of things that I don't intend". // Alice, Through the Looking Glass

  8. #8
    Junior Member
    Join Date
    Jun 2003
    Posts
    19

    Wait, don't kill the subject yet!

    Hopefully I am not talking about a dead subject because I, too, would like to understand what the heck I am doing with all this. I am a little confused why the __proto__ is necessary. Before I even get confusing let me just shoot out an example of what I am confused with. In one of the above codes I changed things around just a little to get rid of the __proto__ and do the same thing (or so I thought). Take a look:

    Code:
    pseudoSuperClass = {};
    pseudoSuperClass.superprop = "set superprop value";
    
    pseudoSubClass = {};
    pseudoSubClass.__proto__ = pseudoSuperClass;
    
    pseudoSubClass.subprop = "set subprop value";
    
    // ORIGINAL CODE //
    //pseudoInstance = {}
    //pseudoInstance.__proto__ = pseudoSubClass;
    
    // CODE I THOUGHT WOULD DO SAME THING //
    pseudoInstance = new pseudoSubClass();
    pseudoInstance.prop = "set prop value";
    
    trace(pseudoInstance.prop); // set prop value
    trace(pseudoInstance.subprop); // set subprop value
    trace(pseudoInstance.superprop); // set superprop value
    Perhaps you can see what I am trying to do. I thought that by creating a new instance of pseudoSubClass I would inherit the ".subprop" and ".superprop" but it doesn't work. I don't understand why. Any thoughts?

    * Oh, and thank you for putting so much effort into the explanations. Although I do not pick up on them right away it sure does help a lot, especially with great examples.
    Last edited by padnpen; 06-16-2003 at 01:21 PM.

  9. #9
    thinking is design retrotron's Avatar
    Join Date
    Apr 2003
    Location
    Utah
    Posts
    141
    Just for kicks. Look at this code. I've created my own inheritance scheme. I'll explain it below.
    code:

    // create my own inheritance scheme //

    // top level object, so "top level", in fact, that it is just a function(-object)
    Object.name = "Object";
    trace(Object); // a function
    trace("this object: " + Object.name); // the function(-object)'s name

    Object.containerObject = {};
    Object.containerObject.name = "Object's containerObject";
    trace("\n" + Object.containerObject); // a subobject, attached to another object (Object)
    trace("this object (atteched to Object): " + Object.containerObject.name); // the subobject's name
    Object.containerObject.parentPointer = Object;
    trace(Object.containerObject.parentPointer); // a function, because it points to a function (Object)
    trace("this container object points to: " + Object.containerObject.parentPointer.name); // the name of what this pointer points to

    Spaceship = {};
    Spaceship.name = "Spaceship";
    Spaceship.parentPointer = Object.containerObject;
    trace("\n" + Spaceship); // an object
    trace("this object: " + Spaceship.name); // the object's name
    trace(Spaceship.parentPointer); // an object, because it points to the "containerObject" attached to "Object"
    trace("this object points to: " + Spaceship.parentPointer.name); // the object this pointer points to

    Spaceship.containerObject = {};
    Spaceship.containerObject.name = "Spaceship's containerObject";
    trace("\n" + Spaceship.containerObject); // a subobject, attached to another object (Spaceship)
    trace("this object (attached to Spaceship): " + Spaceship.containerObject.name); // the subobject's name
    Spaceship.containerObject.parentPointer = Spaceship;
    trace(Spaceship.containerObject.parentPointer); // an object, because it points to an object (Spaceship)
    trace("this container object points to: " + Spaceship.containerObject.parentPointer.name); // the name of the object this pointer points to

    Rwing = {};
    Rwing.name = "Rwing";
    Rwing.parentPointer = Spaceship.containerObject;
    trace("\n" + Rwing); // an object
    trace("this object: " + Rwing.name); // the object's name
    trace(Rwing.parentPointer); // an object, because it points to the "containerObject" attached to "Spaceship"
    trace("this object points to: " + Rwing.parentPointer.name); // the object this pointer points to

    Rwing.containerObject = {};
    Rwing.containerObject.name = "Rwing's containerObject";
    trace("\n" + Rwing.containerObject); // a subobject, attached to another object (Rwing)
    trace("this object (attached to Rwing): " + Rwing.containerObject.name); // the subobject's name
    Rwing.containerObject.parentPointer = Rwing;
    trace(Rwing.containerObject.parentPointer); // an object, because it points to an object (Rwing)
    trace("this container object points to: " + Rwing.containerObject.parentPointer.name); // the name of the object this pointer points to


    When you run it, you get:
    Code:
    [type Function]
    this object: Object
    
    [object Object]
    this object (atteched to Object): Object's containerObject
    [type Function]
    this container object points to: Object
    
    [object Object]
    this object: Spaceship
    [object Object]
    this object points to: Object's containerObject
    
    [object Object]
    this object (attached to Spaceship): Spaceship's containerObject
    [object Object]
    this container object points to: Spaceship
    
    [object Object]
    this object: Rwing
    [object Object]
    this object points to: Spaceship's containerObject
    
    [object Object]
    this object (attached to Rwing): Rwing's containerObject
    [object Object]
    this container object points to: Rwing
    First there is the Object (that's what it's called) native to Actionscript. This is at the top of the inheritance chain. When you trace it, it is just a function, so it's not inheriting from anything else. Then I attach an object called "containerObject" to Object. To "containerObject" I give it a property: "parentPointer". I set parentPointer equal to Object. So "containerObject" now has a property called "parentPointer" which points to Object.

    Next I create an object called "Spaceship". I give Spaceship a property called "parentPointer" too. I set parentPointer equal to Object.containerObject. That is, I point Spaceship to Object's containerObject rather than to Object itself. So Spaceship points to Object's containerObject, and Object's containerObject points to Object.

    Then I attach an object called "containerObject" to Spaceship. I give containerObject a property called "parentPointer". I set parentPointer equal to Spaceship. So Spaceship's containerObject points to Spaceship, and Spaceship points to Object's containerObject, and Object's containerObject points to Object.

    Then I create a new object called "Rwing". I give Rwing a property called "parentPointer". I set parentPointer equal to Spaceship's containerObject. So now Rwing points to Spaceship's containerObject, and Spaceship's containerObject points to Spaceship, and Spaceship points to Object's containerObject, and Object's containerObject points to Object.

    Finally, I attach an object called "containerObject" to "Rwing". I give Rwing's containerObject a property called "parentPointer". I set parentPointer equal to Rwing. So Rwing's containerObject points to Rwing, and Rwing points to Spaceship's containerObject, and Spaceship's containerObject points to Spaceship, and Spaceship points to Object's containerObject, and Object's containerObject points to Object.

    Maybe this will be a helpful diagram:
    Code:
    Object [a function]
      ^
      |
      |
    containerObject [an object attached to Object, pointing to Object]
      ^
      |
      |
    Spaceship [an object, pointing to Object.containerObject]
      ^
      |
      |
    containerObject [an object, attached to Spaceship, pointing to Spaceship]
      ^
      |
      |
    Rwing [an object, pointing to Spaceship.containerObject]
      ^
      |
      |
    containerObject [an object, attached to Rwing, pointing to Rwing]
    That's the tree of inheritance. Each object has a "containerObject" attached to it. Each object (including the containerObject's) have a "parentPointer" property that points to the next object up the tree.

    So is inheritance here working? Yep. Notice that I trace the .name property of something through the parentPointer. That means it's working. I could attach some functions to these objects and they would now be accessible to lower objects via "parentPointer".

    Flash works just like this, except "prototype" is what I've called "containerObject" here and "__proto__" is what I've called "parentPointer".

    So that's how I'm understanding it right now.

    absconditus.com // experiments in actionscripted design

    "I really must get a thinner pencil. I ca'n't manage this one a bit: it writes all manner of things that I don't intend". // Alice, Through the Looking Glass

  10. #10
    thinking is design retrotron's Avatar
    Join Date
    Apr 2003
    Location
    Utah
    Posts
    141
    Hey padnpen, thanks for stopping by.

    The reason your code didn't work is because you tried to create a "new" instance of an object. This is not possible in Flash.

    For example, look at this:
    code:

    thisObject = {};
    trace(thisObject); // output: [object Object]

    thisObj2 = new thisObject();
    trace(thisObj2); [undefined]


    Notice that thisObject is an object (you defined it as such by giving it empty curly braces). When you create an object, an object just is an instance, so you can't create an instance of an instance (by definition).

    You can only create new instances of functions. Look at this:
    code:

    thisObject = function() {};
    trace(thisObject); // output [type Function]

    thisObj2 = new thisObject();
    trace(thisObj2); // output [object Object]

    In Flash, "functions" are really what a "class" is. With MX we have the ability to create "instances" of these functions, and these "instances" are the "objects". In hardcore OOP languages, a class isn't really a "thing", it doesn't "exist". It is just a set of instructions for creating a "thing" (an object) if and when we do create instances of the class. But in ECMA-262 languages, a function is a "thing", it does "exist", and we can use it anytime we want. So the "class" in actionscript is really just a function that we have the ability to create instances from. Some think this is more flexible than, say, Java (see some of the docs I posted above).

    absconditus.com // experiments in actionscripted design

    "I really must get a thinner pencil. I ca'n't manage this one a bit: it writes all manner of things that I don't intend". // Alice, Through the Looking Glass

  11. #11
    half as fun, double the price senocular's Avatar
    Join Date
    Feb 2002
    Location
    San Francisco, CA (USA)
    Posts
    4,361
    padnpen, pseudoSubClass is an object, not a function. pseudoSubClass() is nothing.

    What that code demonstrated was that the functions only serve as a method of assigning __proto__ properties to objects. Here we only have objects and the __proto__ property is assigned manually. The function, when used as a constructor (new functionName()) assigns __proto__ to point to its prototype object, which, itself, is just an object.

    In the pseudo example, its just objects being linked to objects manually without the use of function constructors to do it for us.

    Let me try to outline the procedure taken by Flash in normal inheritance.

    First the normal code so you can see it all at once with no commenting:
    code:

    SuperClass = function(){
    this.superInternalValue = "mySuperInternalValue";
    }
    SuperClass.prototype.superProtoValue = "mySuperProtoValue";

    SubClass = function(){
    this.internalValue = "myInternalValue"
    }
    SubClass.prototype = new SuperClass();

    instance = new SubClass();

    trace(instance.internalValue); // myInternalValue
    trace(instance.superProtoValue); // mySuperProtoValue
    trace(instance.superInternalValue); // mySuperInternalValue
    trace(instance.watch); // [type Function]
    trace(instance.somethingRandom); // undefined



    Now with commenting explanations

    code:

    // Flash begins reading code...

    // User defines function, save function as "SuperClass"
    // in the current timeline.
    SuperClass = function(){
    // when this function is run, set a property in
    // the current 'this' object, whatever it may be
    // to be called "superInternalValue" with the value
    // "mySuperInternalValue"
    this.superInternalValue = "mySuperInternalValue";
    }
    // In defining this function, automatically add
    // a new object to SuperClass called "prototype"
    // SuperClass.prototype = new Object(); As a new object
    // the current __proto__ references Object.prototype.

    // User adds a "superProtoValue" property to the
    // prototype object with value "mySuperProtoValue"
    SuperClass.prototype.superProtoValue = "mySuperProtoValue";


    // User defines function, save function as "SubClass"
    // in the current timeline.
    SubClass = function(){
    // when this function is run, set a property in
    // the current 'this' object, whatever it may be
    // to be called "internalValue" with the value
    // "myInternalValue"
    this.internalValue = "myInternalValue"
    }
    // In defining this function, automatically add
    // a new object to SubClass called "prototype"
    // SubClass.prototype = new Object(); As a new object
    // the current __proto__ references Object.prototype.

    // User replaces the just now created SubClass.prototype
    // object with a different object, the return value of a
    // new SuperClass function call.
    SubClass.prototype = new SuperClass();
    // ...going back to the SuperClass function to run it:
    //SuperClass = function(){
    // the 'new' keyword was used with this function call
    // so make a new hidden object and assign it to 'this':
    // var this = new Object();
    // initially __proto__ of this is to Object.prototype

    // now set superInternalValue property for this:
    // this.superInternalValue = "mySuperInternalValue";

    // since 'new' was used set the __proto__ of the new
    // object 'this' is set to to be the prototype object
    // of this function. This way, all objects created
    // by this function will have the same common reference
    // for methods and properties:
    // this.__proto__ = arguments.callee.prototype;

    // set constructors too
    // this.constructor = this.__constructor__ = arguments.callee;

    // again, since new was used, we need to automatically
    // return the this object:
    // return this;
    //}
    // the returned object then gets assigned to be SubClass.prototype

    // User defines "instance" in the timeline to be the return of
    // a new SubClass call.
    instance = new SubClass();
    // same thing happens before as with
    // SubClass.prototype = new SuperClass();
    // only this time its with the SubClass. instance gets a
    // __proto__ which points to SubClass.prototype.

    // User attempts to access variables.
    trace(instance.internalValue);
    // Flash searches the instance object for a variable called
    // "internalValue". One is found. Its value, "myInternalValue"
    // is returned.

    trace(instance.superProtoValue);
    // Flash searches the instance object for a variable called
    // "superProtoValue". Nothing is found. When nothing is found
    // Flash then accesses that object's __proto__ property finding
    // where it leads. If a valid Object, Flash searches that object
    // for the variable trying to be accessed. As set by the
    // new SubClass() call, instance's __proto__ points to the
    // SubClass.prototype object, so Flash searches that object for a
    // variable called superProtoValue. None is found. Flash again
    // looks for __proto__. One is found and it leads to the
    // SuperClass.prototype object. This is because the current object,
    // Subclass.prototype, is an instance of SuperClass meaning it was
    // made with new SuperClass wherein its __proto__ was set to be
    // SuperClass.prototype. In searching SuperClass.prototype, the
    // variable is found and "mySuperProtoValue" is returned

    trace(instance.superInternalValue);
    // Flash searches the instance object for a variable called
    // "superInternalValue". Nothing is found. The __proto__
    // is then referenced leading to SubClass.prototype. The
    // property is found and "mySuperInternalValue" is returned. This
    // value exists in SuperClass.prototype because it was set in
    // the new SuperClass() call.

    trace(instance.watch);
    // Flash searches the instance object for a variable called
    // "watch". Nothing is found. The __proto__ is
    // then referenced leading to SubClass.prototype. Again,
    // nothing is found. That __proto__ is referenced leading to
    // SuperClass.prototype. Nothing is found there either.
    // Continuing, Flash references that object's __proto__. As
    // it stands now, since SuperClass.prototype is just a normal
    // object, its __proto__ leads to Object.prototype. Flash
    // looks there and finds Object.watch and returns that function.

    trace(instance.somethingRandom);
    // Flash searches the instance object for a variable called
    // "superInternalValue". Nothing is found. The __proto__
    // is then referenced, searched, etc. Not found. Each object
    // in that __proto__ linking is searched until reaching the
    // Object.prototype. When not found there, Flash attempts to
    // go for the __proto__ but Object.prototype has no __proto__
    // so the search is over and undefined you get.



    If you're following this alright, let me show you something not to do You know that Object.prototype is the last link in the chain right? __proto__ always references an object of some sort - and that object's __proto__ either references some other object's prototype or Object.prototype - either way eventually leading to Object.prototype once you get through all the __proto__ chains. So, something you don't want to do is try to go and set Object.prototype's __proto__. If you set that to some object, no matter what the object, you're getting yourself into trouble since you are making an infinite __proto__ loop. Go ahead and try it:

    code:
    Object.prototype.__proto__ = {};



    Last edited by senocular; 06-16-2003 at 03:01 PM.

  12. #12
    thinking is design retrotron's Avatar
    Join Date
    Apr 2003
    Location
    Utah
    Posts
    141
    Whoa, that really tripped me out, senocular and I posting at almost exactly the same time. I didn't know where all that extra text came from.

    Anyways, again, a great explanation from senocular.

    Given what he just said, let me say that in my "pseudo-inheritance" code above, it does not exactly parallel how Flash works. I set
    code:

    Object.containerObject.parentPointer = Object;


    This doesn't happen in Flash. Object.prototype does not have a __proto__ pointing the prototype to Object itself.
    code:

    trace(Object.prototype); // output [object Object]
    trace(Object.prototype.__proto__); // output: undefined


    absconditus.com // experiments in actionscripted design

    "I really must get a thinner pencil. I ca'n't manage this one a bit: it writes all manner of things that I don't intend". // Alice, Through the Looking Glass

  13. #13
    Junior Member
    Join Date
    Jun 2003
    Posts
    19
    I'm understanding this more and more as I read the posts for the seventy thousandth time.

    One thing I think would help is understanding how this is practically applicable. I'm not asking for you to conjur up some example because I believe you have both been doing a lot already. So my question is where do you use this kind of thing? Aside from creating a database with properties is there a practical use for such a complex heirarchy?

    BTW, I am loving the step by step explanations. That's EXACTLY what I need and feel fortunate that there are people out there willing to generously offer their knowledge. So, thanks!

  14. #14
    half as fun, double the price senocular's Avatar
    Join Date
    Feb 2002
    Location
    San Francisco, CA (USA)
    Posts
    4,361
    this is a 'kind of' applicable example - notably in terms of gaming. Its not, itself, a game, but you can see how it might be applied (follow this discussion up to the examples).

    http://www.actionscript.org/forums/s...threadid=26314

    here there are ... shoot I forgot haha. I think its herbivore and carnivore objects which both inherit from the same creature object. The reason this is done is so that any creature property or method that all creatures would have wouldnt have to be written over again for each class which should also have them - ie any creature, ie any herbivore or carnivore.

    ... there are other more 'Flashy' (or or relating to something more typical in Flash) examples but that one above it what came to mind first.

  15. #15
    Junior Member
    Join Date
    Jun 2003
    Posts
    19
    Haha, I saw that the other day and giggled at those Alf-looking creatures. That's pretty cool.

    I can see where this type of code would be useful for games, instead of giving each character the same set of properties you can just share similar ones of other characters. I can see how that would not only eliminate error but be more efficient for coding.

    Although I love games I'm trying to learn how to make websites that kick butt because I'm pretty sure that I can make a buck or two at that (although I would give that up in a heartbeat to make games). So is this type of structure helpful with websites?

    I tried practicing some of what you and retro have been talking about by creating buttons that share the same properties. While I was successful in doing that I wondered if there was more I could do. To be honest, it seemed like a complicated way of doing a pretty simple thing. Don't get me wrong, I was darn proud when I got it working correctly.

    Have you used or run across this structure in general websites (without games)?

  16. #16
    half as fun, double the price senocular's Avatar
    Join Date
    Feb 2002
    Location
    San Francisco, CA (USA)
    Posts
    4,361
    Components! Theres a lot of super/subclassing going on with them Thats a practical example. Even basic movieclip based components make a class which is inserted into the __proto__ chain of a movieclip instance through using Object.registerClass.

    When making a component a class for the component is made and then Object.registerClass is used to associate that class with a linker ID from a library item (the component itself). Then, when that Movieclip is attached or placed on the screen, Flash takes that movieclip instances __proto__ and points it to the prototype of the Class you defined for that component. Because of this, however, you have to be sure to set your component class's prototype to be a new MovieClip() so that the movieclip instance will have access to normal movieClip properties like it did before.

    Ex:
    Normal movieclip instance:
    Code:
    [movieclip]
     V
    [MovieClip.prototype]
     V
    [Object.prototype]
    Here it is when associated with a Class using Object.registerClass, but that class's prototype was NOT set to be a new MovieClip():
    Code:
    [movieclip]
     V
    [CustomClass.prototype]
     V
    [Object.prototype]
    Here it is again, but your class's prototype was set to be a new movieclip:
    Code:
    [movieclip]
     V
    [CustomClass.prototype]
     V
    [MovieClip.prototype]
     V
    [Object.prototype]
    setting the new MovieClip() added the movieclip prototype in the chain of __proto__ references so that movieclip instance would be able to find a method like hitTest if it needed to (which exists for all movieclips in the MovieClip.prototype).

  17. #17
    thinking is design retrotron's Avatar
    Join Date
    Apr 2003
    Location
    Utah
    Posts
    141
    fgf wanted me to build one of those environments in the as.org thread too, someday I'll get around to that. It's always someday.

    I almost never build games...in fact, now that I think about it, I can't ever remeber doing so. But I do build websites and applications.

    One place I find OOP particularly useful is with data structures. Data structures are notorious for doing something over and over again. Simple example: you query a database and get a list of email addresses. Then you display those email address with a loop. This entire process happens time and time again in applications. By packaging this whole process up into a single class you have something that is not only portable to other applications, it makes your life much easier. All the code goes in one place. Then when it comes time to retreive and display records, I can just create a new instance of the class and execute the appropriate methods. That usually results in about 3 or 4 lines of code. Much nicer that way.

    absconditus.com // experiments in actionscripted design

    "I really must get a thinner pencil. I ca'n't manage this one a bit: it writes all manner of things that I don't intend". // Alice, Through the Looking Glass

  18. #18
    Junior Member
    Join Date
    Jun 2003
    Posts
    19
    That sounds very interesting. I can see how, really, an entire website could be created with database information that was 'class' ified for easy formatting, generating, etc. If only I knew more about database programs...

    Perhaps I will get lucky enough to find the right situation where I can not only learn about databases but then apply this kind of structure to it in Flash.

    Thank you both!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  




Click Here to Expand Forum to Full Width

HTML5 Development Center