Saturday, April 24, 2010

OOP Concepts in Actionscript 3.0: Inheritance vs. composition

A simple rule of thumb determines whether the relationship between classes is one that warrants inheritance or composition. If you can say class A "is a" class B, you're dealing with inheritance. If you can say class A "has a" class B, the relationship is one of composition.

Here are some examples of inheritance:

* Cat "is an" animal
* Engineer "is an" employee
* Rugby "is a" sport

Here are examples of composition:

* Wall "has a" brick
* Computer "has a" keyboard
* School "has a" teacher


So what is the difference in how inheritance and composition are implemented? Let's compare how this works, starting with inheritance:

Animal.as ====

package {
public class Animal {

public var furry:Boolean;
public var domestic:Boolean;

public function Animal() {
trace("new animal created");
}
}
}


The Animal.as code is the base Animal class, which you will now extend using inheritance with a Cat class:

Cat.as

package {
public class Cat extends Animal {
public var family:String;
public function Cat() {
furry = true;
domestic = true;
family = "feline";
}
}
}


Let's do a quick test of this class by instantiating it on the main Timeline of a blank FLA file:

import Animal;
var myCat:cat = new cat();


================================================================================

Let's take the Brick class created earlier. In this next example you'll create a Wall class that uses composition to instantiate instances of the Brick class:

Wall.as

package com.adobe.ooas3 {
import com.adobe.ooas3.Brick;
public class Wall {

public var wallWidth:uint;
public var wallHeight:uint;

public function Wall(w:uint, h:uint) {
wallWidth = w;
wallHeight = h;
build();
}
public function build():void {
for(var i:uint=0; i for(var j:uint=0; j var brick:Brick = new Brick();
}
}
}
}
}

In the code above, the Wall class accepts two arguments passed to its constructor, defining the width and height in bricks of the wall you want to create.

Let's do a quick test of this class by instantiating it on the main Timeline of a blank FLA file:

import Wall;
var myWall:Wall = new Wall(4,4);