One of the most fundamental rules of object oriented programming is the principle of encapsulation.
The basic principle of encapsulation is to prevent a class’s inner workings from being exposed to outside classes.
Before going deeper into encapsulation, let’s talk about the concept of API or Application Programming Interface.
Simply, API refers to the public available interface of a given application. If we use the Google search engine as an example, the API is the public available functions like the search button, advanced search and the “I feel lucky” function etc.
The inner workings of Google search are not exposed and are therefore not a part of the API. Any given API is public, within its own scope. No exceptions on that rule.
When writing ActionScript 3.0 classes, you should also define an API. In this context, the API refers to the public available methods inside your class files. A well considered API is the first step towards proper encapsulation. You define your classes’ API by means of access modifiers.
The access modifiers in ActionScript 3.0 are keywords telling the compiler what methods are available by other objects. Proper use of access modifiers is essential for defining your API and maintaining good encapsulation. The access modifiers are used to encapsulate the inner workings of your class as private members while the API is defined with the public modifier.
Here is a short explanation of the access modifiers:
Public: Class members are accessible by all objects.
Internal: Class members are accessible from classes in the same package and the class itself.
Protected: Class members are accessible by subclasses and the class itself.
Private: Class members are accessible from that class only.
Think of your classes as black boxes with an input and an output. You put something into the box which is being processed and the result is being output. This is essentially the API. You do not need to know what happens inside the machine.
Just like a coffee maker: You add water and coffee beans and the machine outputs coffee. What happens inside the machine is of no importance to you, as long as fresh and good smelling coffee is coming out the other end.
Transferring the coffee maker analogy to classes, we define the power switch, the water intake and the funnel for the coffee beans as public class members. The internal workings like the circuit board and the inner tubing for water processing are defined as private class members.
Indeed a coffee maker has a well defined API and good encapsulation!
Imagine what would happen, if the producer of the coffeemaker accidentally had exposed the temperature adjustment on the internal water boiler. At some point, someone would raise the internal temperature to maximum eventually setting the house on fire!
This is what encapsulation is all about: Protecting your application from unintended usage avoiding unexpected behavior.
Most newbies have no clue of encapsulation and declares all class members public, thereby exposing the inner workings of the class. When another developer is taking over the project it is very easy to break the application, because a proper API was not defined.
When a proper API for your application is defined and good encapsulation is enforced, it is much easier to reuse code. A well written class or set of classes can easily be reused in other applications when they have no dependencies.
This is why classes cannot depend on other classes unless they are a part of the same API. In that case, the classes would be placed inside the same package and would share the same API.
Skilled OOP developers are capable of producing complex functionality on the fly by reusing code. Without a well defined API and strong encapsulation this would not be possible.
If you look at the Flash and Flex intrinsic classes (aka factory classes) they all use proper encapsulation and well defined APIs. Therefore the DisplayObject class or the Event class can be re-used over and over again. When you write your own classes, try to imagine that you write intrinsic factory classes.
When defining your API you should never declare variables as public. This is simply a no go. Always declare your variables private or protected (or in some cases internal).
If a variable is a part of your API then use setter and getter methods to expose the value of that variable, so the variable itself is never directly exposed.
This way you can always check if a variable being set is of a wrong type or is out of acceptable range before setting it. This way you can throw a runtime error, warning other developers (or yourself) that urgent attention is required. Otherwise, the application will keep on running producing unexpected results.
Let’s take a look at this example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | package { public class Car { private var _numberOfWheels : uint = 0; function Car(){ } public function set numberOfWheels(n : int):void{ if(n < 4 || n > 8) throw new ArgumentError("Invalid number of wheels is being set."); if(!isEven(n)) throw new ArgumentError("Only an even number of wheels can be set."); _numberOfWheels = n; } public function get numberOfWheels():int{ if(_numberOfWheels == 0) throw new Error("Number of wheels have not been set."); return _numberOfWheels; } private static function isEven(n : Number):Boolean { return(n & 1) == 0; } } } |
What would happen if the _numberOfWheels variable was declared as public? Mayhem would rule, because you would have no ways of checking if the number of wheels on your car was set to 2. No functional car can have only 2 wheels. What if the value was set to 5? No cars that I know of have 5 wheels, but some large trucks might have 6 wheels. I’m sure you get the point by now.
The above approach produce a little more code, but in the end you are building better applications. Anyway, who told you that the goal was writing as little code as possible? In the end the goal is flexible, scalable and reusable software.
If you are consistent and use proper encapsulation at all times, you are on your way of becoming a better object oriented programmer. You will enjoy a stronger and less error prone application.
You will set yourself in a position of being able to develop larger and more complex structures while being able to reuse your code.
Leave a Reply
You must be logged in to post a comment.