Archive for September, 2007

Internal, protected, public, private 101

September 23, 2007

Public, internal, protected methods should be marked “override” in a derived class when be ovverriden. Also the visibility and signature of these methods cannot be changed by the derived class.

Static and private methods are hiding from the outside world.
So a derived class is unaware of its parent class’ static/private members, which means you can create static or private methods with the same name but different signatures in the derived class than the static/private methods in its parent classes.

Static methods are treated differently than non-static ones.
A static method can co-exist with an instance method with the same name. The signature can also be different.

Example:

package test
{
import flash.display.Sprite;

public class InheritanceTest01 extends Sprite
{
public function InheritanceTest01()
{
var a1:A1 = new A1();
//a1.sayHi(”we should go beers”, “have fun”);
//a1.walk(12);
A1.sayHi();
}
}
}

class A
{
private function sayHi():void
{
trace(”hi!”);
}

protected function walk(distance:Number):void
{
trace(”I will walk for “+distance+” miles.”);
}

public function run():void
{
trace(”I run!”);
}

internal function sleep(duration:Number):void
{
trace(”I am going to sleep for “+duration+” hours.”);
}
}
class A1 extends A
{
public function A1()
{
super();
sayHi(7);
}
/*
public function sayHi(w1:String, w2:String):void
{
trace(”Oh hi! I am just saying “+w1+” and probably “+w2+”.”);
walk(12);
run();
sleep(1.5);
}
*/
private function sayHi(times: uint):void
{
if(!times)return;
for(var i:uint =0 ; i<times; i++)
{
trace(”hi”);
}
}
static function sayHi():void
{
trace(”Ciao!”);
}

override protected function walk(distance:Number):void
{
trace(”I will walk for “+distance/2+” miles and then another “+distance/2+” miles.”);
}

override public function run():void
{
super.walk(1);
trace(” then “);
super.run();
}

override internal function sleep(duration:Number):void
{
super.sleep(duration);
trace(”and I am going to sleep for another “+duration+” hours!”);
}
}

Concurrent/Hierarchical states in State pattern and MVC pattern: Take two

September 23, 2007

Concurrent states in a state machine have behaviors that are independent of other states. For example, in a Flash video player, the “fullscreen” state is independent of “play”/”pause” states.

In a state machine, states have hierarchies. Some states that show relatedness of contexts can be grouped together; Child states are not accessible until their parent states are active. Theoretically, each set of concurrent states should have their own state manager. (In practice, if there is only two set of concurrent states, I find it just convenient to combine the two into one context object and have the base state includes interfaces that should be used by the other set of concurrent states. )

State pattern and MVC pattern revisit: Take one

September 22, 2007

Use case: You need to change the behaviors of your type code at run-time. For example, clicks on “play” button sometimes play a video clip and in other cases do nothing, depending on the context. (whether the video clip is playing or not.) The bad smell in your code usually is signaled by the presence of case-like conditional statements. It gets too complex when you need to place in many of the methods the same logical case/if-else switches to tackle the context and execute different code. The solutions can be “Replace Conditional with Polymorphism“, “Replace Type Code with Subclasses” or “Replace Type Code with State/Strategy” (Martin Fowler: Refactoring).

In GUI design, the run-time states and behaviors of a set of user interfaces are determined by a set of predefined rules. These rules are usually procedural-like and can be visually presented in flow charts. Using a statechart, we can split the logics into a group of self-sustained substate objects and thus make our program much easier to control.

In order to make it work, you need to set up a polymorphic structure:

1. A generic state interface. It contains two methods: enter() and exit(). Implement enter()/exit() in the concrete classes to perform type dependent setups and cleanup (such as hiding/exiting/fading out some components, etc.).

2. An application specific state interface. In this interface, define services that all the subclasses need to carry out, such as the following:

public function viewProfile(index:Number):Void
public function handleIndexSelect(info:Object):Void

3. An abstract/base state class that implements interfaces 1 and 2.

4. Most of times, instead of stuffing all the service methods in the base state class in step3, you will find it convenient to create a couple of concrete classes that provide common services more than one of the substates will perform and that are independent of the context, such as playVideo(index:uint):Void, pauseVideo():Void, setRepeatAll(v:Boolean):Void, handleClipComplete(evt:Object):Void, etc..

5. A state manager. State manager is the context object. It has the following major responsibilites:

a. Stores references, as well as defines accessors to all the substate objects.

b. Accessors to get and set the current state object. Like this:

public function setState(v:AbstractState):Void
{
_state.exit();
_state = v;
_state.enter();
}

c. Initializes the entry substate object (or to initialize all the substates) and set the current state to that object when itself is initialized.

6. All the concrete substate classes. The classes need to store a reference to the main timeline (or the Document class if in ActionScript 3), as well as references to each of the common service provider classes as mentioned in step3 if any. Each of the classes has the following responsibilities:

a. Implements enter() and exit(). enter() needs to assign event handlers to all the UI controls.

b. Defines and implements context sensitive behaviors. They are usually handlers of UI events.

c. At least one of the methods in step b. needs to call the state manager to switch the current substate.

“a file found in the source-path must have the same package structure”

September 21, 2007

When compiling an ActionScript file, the source path needs to be clearly defined or otherwise the compiler will complain with the following message:

"A file found in the source-path must have the same package structure..."

This can be fixed by adding the “source-path” definition in the command line, like this:

H:\stuff\lab\AS3\test>c:\flex_sdk_2\bin\mxmlc -source-path=H:\stuff\lab\AS3\ EmployeeTestDrive.as

when compiling the following .as file which resides in “H:\stuff\lab\AS3\test” folder:

package test
{
import flash.display.Sprite;
import flash.text.TextField;


public class EmployeeTestDrive extends Sprite
{
private var _foo:TextField;
public function EmployeeTestDrive()
{
_foo = new TextField();
_foo.text = “hello world!”;
addChild(_foo);
var employee:Employee = new Employee(”sdk_dev222″);
}
}

}

////
class Employee
{
function Employee(id:String)
{

}
}

Static methods 101 in AS3

September 14, 2007

Static methods cannot be overridden in subclasses (doesn’t allow for polymorphism) since they are resolved at compile time.

Each class can define their own static methods with the same name/signature of the static methods as defined in their subclasses/superclasses. Same thing for static variables. You cannot use “override” in such a situation since static methods and variables don’t exist within the inheritance chain of the class in AS3 while polymorphism is determined by AVM at run-time.

It is permissible to define an instance property/method using the same name as a static property/method since instance properties/methods are resolved at run-time. (Note that if the static variable has an accessors method which has the same name as a variable, your code won’t work properly.)

The following code will compile:

class A
{
public var NAME:String = “A”;

public static var NAME:String= "A Static";

public function name():String
{
return this.NAME;
}


public static function name():String
{
return A.NAME;
}


protected function walk():void

{

trace(”an A is walking.”);

}

}

Class B extends A

{

//Cannot say “override static function walk()” since we are NOT overriding an instance method.

public static function walk():void

{

trace(”Everyone who is B is walking.”);

}

}