















































Estude fácil! Tem muito documento disponível na Docsity
Ganhe pontos ajudando outros esrudantes ou compre um plano Premium
Prepare-se para as provas
Estude fácil! Tem muito documento disponível na Docsity
Prepare-se para as provas com trabalhos de outros alunos como você, aqui na Docsity
Encontra documentos específicos para os exames da tua universidade
Prepare-se com as videoaulas e exercícios resolvidos criados a partir da grade da sua Universidade
Responda perguntas de provas passadas e avalie sua preparação.
Ganhe pontos para baixar
Ganhe pontos ajudando outros esrudantes ou compre um plano Premium
Building Object-Oriented Applications in Flash 5
Tipologia: Notas de estudo
1 / 55
Esta página não é visível na pré-visualização
Não perca as partes importantes!
















































This will be an attempt to explain what object-oriented programming is, why it is useful, and how it may apply to programs you make in Flash 5. It assumes you are reasonably familiar with actionscript, (or javascript, with an asterisk or two). It will attempt to explain OO programming as a new system, unrelated to 'normal' procedural programming styles. This tutorial will likely be most useful (and least annoying) to either those who have almost no programming experience, or those who have an advanced understanding of OO techniques but are coming from a different language. Inexplicably, it is aimed at all you fine people in the middle.
The hurdle to learning OO programming is not that it is complicated. It isn't. The hurdle is that it requires you to change the way you think about things that you already understand. That is tough. It requires the same mind shuffle that happens when you meet an 'internet friend' in person for the first time. Especially if you had the gender wrong. It's the same person - nothing has changed - yet it's also a new person with a face and voice (and perhaps, unbelievably, breasts or a beard...). At first you just deny it. You mentally treat the 'online person' and the 'real person' as two different people. That only gets you so far though; there is too much overlap between them. Simple conversations get confusing - you mix them up, and even start to doubt you actually knew him/her/them in the first place. Probably at one point you backtrack, trying to fit old facts to new information. You reread some old e-mail, have a few laughs and perhaps blushes. Things start to slowly gel; it even clarifies the odd thing that seemed out of place. Time goes by, and eventually you get used to it - even expect it. Indeed, before long, you wonder how you could have ever thought it to be otherwise. Things are where they should be. You are now an OO programmer.
So just what is Object-Oriented Programming then? Well, the best place to start may well be with the thing that starts it all off, the humble object.
The Object
personA = new Object();
There it is, personA is an Object. Lets just refresh ourselves on what you can do with an object. You can add properties to an object, like the following:
creating quick objects though:
o = { x:x, y:y, z:{a:a, b:b} }
Note the curlys, commas, colons, and the lack of semi colon at the end.
into boxes, and labeling all the boxes (perhaps somewhat cryptically) according to their contents. This involves thousands of decisions and prioritizations per hour. It's a great test of a marriage if you are ever looking for one.
Bob and Ann are moving. Lets help them by putting their stuff into boxes. Objects are like boxes, luckily, so this will not hurt our backs. It is a little known fact, but Americans are the most 'moving' people in the world (OK, after Tibetan nomads). Three out of five Americans move every five years. That comes to millions and millions of moves. Further research has revealed that in each and everyone of those moves, there has been a box labeled, "important stuff". As a nod to the tremendous value American people put on "important stuff", we'll start with that box.
importantStuff = new Object( ); importantStuff.money = 500; importantStuff.papers = 96; importantStuff.annPassport = "er246vjl"; importantStuff.bobPassport = "kl554mkt";
Can you see that we have added a few items to the box? So far so good. Well, maybe anyway. What if we put in something that is already in a box - for example a jewelry box?
importantStuff.jewelryBox = 1;
That seems right, but when Ann needs to find her necklace, will she be able to? We have put a list of the contents on each box, but her necklace will not be on the list. What we really should do is make a list of what is in the jewelry box, something like:
importantStuff.jewelryBox = new Object( ); importantStuff.jewelryBox.necklace1 = "Pearl"; // fake importantStuff.jewelryBox.necklace2 = "Diamond"; // fake
Now the jewelry box has a list of what is inside it too (we keep our comments to ourselves of course). It isn't a perfect solution for her, because the list is on the jewelry box, inside the closed box. She still needs to open everything to find her necklace. Lucky for us however, this is exactly how objects behave in Actionscript, so we'll just leave the boxes as they are. Hope she doesn't mind.
There we go, we have put an object in an object - a box in a box. It is not a stretch now to see it going the other way too. Say they use two vehicles to move, a car and a truck. Some boxes go into one, some into the other. "Important stuff" ends up in the car, so the necklace can be found at car.importantStuff.jewelryBox.necklace1. This is much like what happened when we created personA and personB. We created them somewhere, and somewhere is always inside an object when you create things in Actionscript. In Ann's and Bob's world, it is easy to see that, eventually, the ultimate container will be Earth, Universe, Om. In Actionscript, OM exists too, taking the form of 'the object they call Object'.
So, these objects sitting in objects seem simple enough, but in order to really understand what is going on with them, we are going to have to dig quite a bit deeper. With this deeper understanding will come great power. Embrace it, feel it surging through your veins. Trust your feelings, Luke. I am your father. More on objects coming up...
The Object - Part II
Let's back up and try putting an object inside personA, just to see how that works.
personA.favs = new Object( );
Check your pulse - when it drops back down to a reasonable level, continue. We have just added a new property to personA, and it happens to be an object rather than text. We can add properties to this new object, favs, by just saying:
personA.favs.site1 = "flash.com"; personA.favs.site2 = "google.com";
This again was the same as saying:
A second consequence of having nested objects is their 'scope'. Scope means something like 'context', in the sense of 'what can be seen/understood from different places/points of view'. Taking the baby metaphor again, the baby can 'see' inside its mother (with a flashlight), but it can not see what its mother sees. In Actionscript you can reference an object's scope automatically - the first place Actionscript will look for a property is the object's own scope.
The feature of boxes that we have been interested in is not the cardboard, it is their 'containerability' (nod to gwb). Containers can be filled with all sorts of things, including other containers. From within a container, you can see all the other objects inside it, but not the ones outside it. And although you may see other containers from within your 'scope', you will not be able to see inside them. Whew, this would be a good time for an example, it's not complicated at all. Let's make yet another personA object:
personA= { name : "Ann", favs : { site1 : "flash.com", test1 : function(){ trace (this.site1) }, test2 : function(){ trace (this.name ) } }, test3: function(){ trace (this.name ) }, test4: function(){ trace (this.site1) } };
personA.favs.test1(); // flash.com personA.favs.test2(); // null (child can't see parent) personA.test3(); // Ann personA.test4(); // null (parent can't see child)
In this example, the 'this' keyword means 'the container that called this function', which is conveniently the container we are trying to see inside. It isn't necessary to understand how that works at this point, but to describe what each 'test' property is returning in plain old English:
test1: The property called site in this container (personA.favs). // which has the value "flash.com"
test2: The property called name in this container (personA.favs). // there is no such property in personA.favs
test3: The property called name in this container (personA). // which has the value "Ann"
test4: The property called site in this container (personA). // there is no such property in personA
What happens if we change test4 to say:
test4: function(){return this.favs.site1;} // note the '.favs.'
Well, happily it now works. What does it return?
test4: The property called site1, in the container called favs, which is in this container. //? Try find the value using the new test4 code...
NAMESPACE
This has pretty much been covered in the last example, but it is worth mentioning specifically. Everything has its place, and that place is given a name. You should be very happy about this, because it is a great way to organize your program. In fact it is how people naturally organize things in the real world. Think of your address. It's probably something like - name, house#, street, neighborhood, city, state, country. The postal system relies on this to find you. Programs used to be written as a bundle of 'names', but as they grew bigger (like to the size of small cities) this became impractical. A better system was needed to organize this complexity. One of the main benefits of object-oriented programming is that it organizes complexity. Everything has an 'address'. From this address you can only see certain things. There are no global variables (properties that can be seen from anywhere) in object-oriented languages for a good reason - you are using object-oriented techniques because you want to organize things. The postal system would be unable to function properly if people were allowed to just use a name for an address, and eventually so does a program.
Key object-oriented concept: It is very important to always be thinking where things should go in your program. How you will do a certain task is often much less important than where you will do it. Compare the importance of location and technique for a couple having sex in a fast food restaurant. It's that kind of thing...
This is probably all very familiar to you from using Flash. Targeting movieclips works just like this. Take the movieclip you call personA, put a movieclip in it called favs. Now from personA's timeline (inside the container personA), if you say this._x it will return personA's _x property. If you say this.favs._x, it will return personA.favs' _x property. If you create the property this.name="Bob", that value will not be able to be seen from inside the favs movieclip (without using _parent that is - nothing's impossible to get at somehow!). This is similar for a reason - movieclips are a type of object like everything else.
Has-a Relations
OK, that was easy enough. You can create objects, objects have properties (which are often called
Template = function() { this.x = 5; this.y = 7; } inst1 = new Template( ); inst2 = new Template( ); inst3 = new Template( ); trace( inst1.x); // 5 trace( inst1.y); // 7 trace( inst2.x); // 5 trace( inst2.y); // 7...
Capitalization Tip
Classes should always start with a capital letter. Instances should always start with a lowercase letter. If you stick with this rule, it will always be easy to tell them apart.
In spite of the fact that a class is merely an abstract idea in the ether, and an instance is so real it leaves a mark when it slaps you, they tend to look eerily similar in a program.
Remember: ClassName - instanceName
The word used in OO terminology for these templates is 'Class' (think 'classify' and 'classification', not 'classroom').
A Class is a template that is used to make new objects, and these objects are called 'instances'. Objects and instances are one and the same thing, and can be used interchangeably (and they often are!). That being said, the word 'instance' usually suggests objects that were created from a class using the new operator, while 'object' is a more general term for all objects.
Because instances come from classes, and classes create instances, they are easier to understand when discussing them both at once, so lets move on to the next section, instances...
Instances - and a brief description of 'New'
Class : A template (used to set properties in an object). Instance : An object (created using a Class).
To tie classes and instances together with what we've learned up to this point:
l instances (objects) are real things that can have properties (like inst1.x has the property x). l instances can be thought of as containers, classes can be thought of as descriptions of things that will go in a container. l instances have a 'scope' they can't (naturally) see out side of... We will see a similar thing applies to classes. l instances are created by classes, and can be related to each other - we have just begun to touch on this topic...
We created a few new objects in the previous section, and though things worked like we probably expected them to, do we really understand what is happening? Let's take a medium close look. Here is a condensed version of the previous code (numbered only for convenience):
How does inst1 end up with the properties x and y? How does actionscript know this is what we want? Let's go through it step by step. First the class is defined. That is just a definition; it has little to do until it is called. The first line to do something (other than setup) is line 6. The right side of an equal sign is always evaluated first, so we'll start there. The word new does many things, but most importantly it creates a new object (box, container...) that has no properties and no name. It then sends this box to whatever class the statement beside it points to, which in this case is the class called Template. Recap: the right side of the equation in line 6 has now sent 'a box with no name' to 'Template'.
Every class expects and receives an empty unnamed box when it is called. This box is given the temporary name "this" when the code block begins, and then its 'dragged' through the class. As it moves through, properties are assigned to it as per the class's instructions, using the "this" keyword. Think of a box going down a conveyer belt, being filled with different objects as it moves. Each step says, "this box gets one of these", "this box gets one of those"... In this example, the box is given two properties, x and y with the values 5 and 7. When the end of the class definition is reached, the box (that now has two new properties) is returned. So what line 6 now says is
inst1 = << a box(object) with two properties, x:5 and y:7 >>
shows this:
A = function() { this.x = 5; // _root.x = 5 return 7; }
var y = A(); trace (_root.x); // 5 trace (y); // 7
As you can see, _root was sent into the function, and assigned to the "this" keyword. When the function was run, the properties assigned to "this" were being assigned to _root, as the trace shows.
Local properties inside a function
What happens if we define a property using the var keyword? A local property is created. Local simply means 'local to the scope of the current object', or perhaps, 'in this container' if you prefer. Kind of like the 'local yokels' in a small town - they are born, raised, and buried in the same small town, and never manage to get out. Here is an example of a local property defined in a class...
A = function() { var temp = 5; this.x = temp; } trace(A.temp); // not here
Where exactly does the property temp live in this example? It is in the 'activation object' (sometimes also called the 'constructor function') portion of function A. Does this mean it could be found by saying A.temp? Well, no, because it is only being defined in this example - the whole activation object section doesn't run at all until A( ) is called. Does this mean it would be available after A is run? No again, because that object is discarded once A is run. In fact, every time a function is run, this activation object is created, and every time it is finished running, the activation object is discarded (though not usually deleted from memory in Flash 5, tsk tsk). So temp lives inside the scope of this temporary object. However, because the activation object has no name, and it is only around when the function is running, it cannot be accessed by any other part of the program (unless you call a function from a function, then the second function can see it with its "this" property). When it finishes running, its local properites are not saved.
People often say that in actionscript 'everything is an object', which is not really right because some things clearly aren't objects, and strangely, some things are more than one object. The function above is two objects (actually it's three, but we'll get to that). There is the reference object called A that behaves like any other object. You can add properties to it, like A.temp, and those properties will be put into the A object. Then you have the block of instructions that make up the function. This is will be the second object, the activation object, that is created every time a function is called.
The usefulness of the first A object is limited. Its biggest job is giving the function block a name so that it can be called. After that you can use its namespace for information about the function itself. An example of such information would be it's classname (for debugging purposes), or a counter that counts the number of instances that have been created from it. Properties in this location will have no effect on running the function, and will not show up in its instances.
The second object, the activaton object, is where the 'building' happens while creating an instance, so it is quite useful of course. It has its own scope, and its "this" keyword is given the box on which it can create or modify properties. This is only part of the story when creating an instance though - perhaps the famous part, but not necessarily the major part as we will see when we dig into the prototype.
The idea of functions having a block of instructions that run when you call them relates very well to Flash. The symbol in the library has information that tells instances what they will look like and how they will behave. What about the other part of the function though, like the 'A object' in the previous example? This location is used for storing information that tells about the object, but is not relevant to the instances. For example all the symbols in the library have a name, but this name isn't given (or relevant) to the instances. If you check 'Update Use Count' in the library, each symbol shows how many times it has been used in your movie. Again, this is a property that is relevant to the class, but not the instances, therefore the logical place for this kind of information is attached to the class object. In actionscript, you can get access to this information (using intance.constructor.temp, but more on that later) where as in Flash it is not available to your instances (only to you, the user).
Though you don't often have a need for this namespace while programming in Actionscript, it sometimes is the perfect place. An example of this would be counter that keeps track of how many instances have been created - much like "Use Count" does in Flash.
Inheritance
Let's go over these in (not too painstaking) detail.
oriented... documents have scrollbars, scrollbars have thumbs (thumbs are the little things you drag on a scrollbar).
Inheritance, and OO programming in general, becomes most useful when you get enough similar classes that they start to somewhat naturally organize themselves (always good to be hopeful!). This is worth mentioning, because many Flash programs are quite simple and not all that big, and have short life spans (nor is the programming even the central focus of many files). It would be overkill to use multiple levels of inheritance to link buttons to pages. Writing small programs is a bit like being the post-master in a small village. You need nothing more than the name of a person to get your mail delivered. If there is a change - someone new moves into town, someone changes houses, even a street name change - you can just keep track of it in your head. You might even laugh at how seriously big city postmasters take obscure rules, or how they debate for hours tiny changes in the postal codes. This is all fair enough; you both get the mail delivered. As long as you recognize that the village system would not work in the city, there is nothing wrong with being 'quick and dirty' when it meets all the requirements - it's probably advisable in fact. You don't want to subdivide mammals>dogs down to atoms, after all. One of the main skill sets in OO programming is finding the right balance between complexity and completeness (the same dilemma a writer faces when writing a short chapter about object-oriented programming in actionscript in fact!).
The Prototype
In previous class examples, there were three places to assign properties. You can attach them directly to the class object, like A.temp. You can have temporary properties inside the class block{ }by using var x = 5. Lastly, you can attach properties to the object ("this") that is passing through the class's activation object when an instance is created. These properties will end up in the new instance. This may seem like a lot of ways to set a property, but there is still one thing you cannot do. There is no way to set a property that belongs to the class, but is available to an instance. That probably sounds strange, so let's look closer. Take the very simple Dog class below:
Dog = function( ) { this.legs = 4; } rover = new Dog( ); fido = new Dog( ); yeller = new Dog( );
don't. They all have a "legs" property, though it comes from Dog.prototype.legs rather than fido.legs. How do you access legs from fido? This is the beauty of it, you access it in just the same way you would access any other property of fido - fido.legs. In fact you don't know, need to know, or want to know where this property came from. That doesn't mean you don't want to put it in the right place and have it stored in the right place when your program runs, just that you want to access it as if it were a property of the instances - rover, fido or yeller. This is all great, but it does poke a few holes in our 'boxes' metaphor that we have been using for objects. Let's clarify then. One can think of objects as boxes with a list of their contents taped to the outside. This still holds true. What is happening inside those boxes however isn't what we would expect from regular cardboard boxes. For this we need a new metaphor.
Inheritance works a bit like sandwiched layers of glass. If you have ever visited Canada or Finland, you probably have seen triple pane windows. You want these. They insulate so well they will actually add heat to your house (btw, 'heat' means 'good' - in case you are reading this from Phoenix - perhaps you use triple pane windows to keep the heat out). What makes these windows relevant here is that just by looking at them you can't tell how many panes they have. Most people only need to look at the heating bill to know, but home builders use a nifty trick. They hold a match in front of the window and count the reflections, the point being that even builders need a trick. So we have three (or more) panes of glass - and we know in the back of our heads that there are multiple panes of glass - but we can't tell how many panes by just looking at them. The last thing to imagine here is that we can slide small cut-out paper shapes in between the different glass layers (don't try this at home - you'll wreck your window!).
You can slide things into different layers, however it will appear as if they are all on the first layer. If you slide one paper in front of another (on different layers), you will only see the one closest to you. The front layer of glass is a bit special, in that you can reach it easily. You can make marks to paper that is on the front layer (modify), add new sheets (add), or take sheets off and throw them out (delete). The deeper layers basically stay the way they are once you set them up, unless you really, really want to change them (becasue it is easy to get cut sandwiching and un-sandwiching the layers (dangerous code!) ). Usually, you just make changes by putting new sheets of paper on the front glass (covering the ones further back) and use that sheet to make changes. Under no circumstances are you allowed to draw on the glass! You learned that when you were four. This seems like a lot to remember, but rejoice -Actionscript takes care of every one of these details for you automatically!
Look at the two illustrations of glass above - do you see how they line up when brought together? Yellow is on the first layer, orange on the second, and purple on the third. What would you do if you
wanted to now modify the center (purple) square? Ans. Tape a new paper to the front - it's too much trouble to take the windows apart.
Properties on an object, then, are less like things drawn on a chalkboard and more like things taped to a window. The first (front) window is your instance. It gets properties set on its level when it is 'instanciated' (created). Properties are attached to it (or, specifically, the nameless object that it will become) using the 'this' keyword. After it is created, a property can be attached manually, by saying instance.x=5. We will find there are a few more ways that properties end up on the instance layer. The second sheet of glass contains the properties that belong to the class (the class that made the instance), and they are located in the Class.prototype. Whatever one adds to the second sheet will be seen by all instances created with the class. To go back to the dog example, if we added the puffyHair property to the Dog.prototype (the second sheet of glass), then all three dogs would now have puffy hair. Old yeller, loyal though he is, would probably not be amused.
There is one point to clear up with our window pane model. A property added to the Class.prototype (the second sheet) appears in all instances of that class. Does this mean that all instances get a 'copy' of that sheet of glass? Well, no. In fact it is the exact same sheet of glass for every instance. Perhaps you prefer to visualize the instance windows all angled toward the lone second sheet of glass, and then as you move from instance to instance, each lines up properly with the second sheet. It probably easier to just make a mental note though that this is the same second sheet for each instance. The sandwiched glass idea describes a single instance well, but not the whole inheritance system. The reason this metaphor 'breaks' is that inheritance is a mental classification system, rather than a physical one. It's not hard to see that all mammals are classified under the same definition of mammal, and if that definition changes, the definition of each mammal will change to incorporate the new information. That type of information shuffling isn't possible with real world objects that are physically related. It doesn't mean a model isn't useful of course, it works very well when describing a single instance, and it nicely explains overriding, as we will see in the next section.
Overriding
We now have a model where all Dogs have four legs, and some dogs have puffyHair. Does our model break if yeller slips while using a bandsaw - and loses a leg? We don't want to make the change Dog.prototype.legs = 3 , because that would affect all dogs (unless we take the bandsaw to the others, hmm...). If we go back to our sheets of glass model, we can see the best place to record this tragic turn of events would be on yeller's first sheet - just the way fido stores information about his personal haircut. That is logical enough, after all it's yeller's personal misfortune, it's not a species-wide tragedy. What happens, though, if you modify yeller's legs property, by saying: