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!”);
}
}

Advertisements

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(). They are directly called by state context object (see #5) when a state decides to switch to another state. Implementing enter()/exit() in the concrete classes to perform type dependent setups and cleanup (such as hiding/fading in 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 responsibilities:

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
{
if(_state!=v)
{
if(_state)_state.exit();
_state = v;
_state.enter();
}
}

c. Initializes the entry substate object (and optionally to initialize all the substates) and set the current state.

6. All the concrete substate classes. The classes need to store a reference to the state context object, and in the case of Flash, 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() usually needs to assign event handlers to all the UI controls and exit() usually removes these event handlers. You don’t switch states within exit() since state manager explicitly calls enter/exit within its setState() (and you will get “Error 1023 Stack overflow” at run-time if you do so.)

b. Defines context sensitive behaviors. They are usually handlers of UI events and can also be a condition such as when a rocket thrusts beyond a certain speed threshold. It’s up to these individual states to decide when to switch states and they do this by informing the state manager which state they choose to go to, like so:

private function gotoZoomOutState():void
{
_stateManager.setState(_stateManager.getZoomOutState());
}

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

I feel this is the point of State pattern in that it partitions all the complicated contextual logic into separate chunks who then individually take care of each condition (in a much more linear fashion since individual states only behave at their own levels and in the case when they need to affect others in the system, they communicate via the state context object). This approach makes coping (develop, maintain and extend) with complex system much easier.

“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.”);

}

}