Posts Tagged “class”

For a special purpose I had to extend a Singleton, to make my system fully flexible. I found complicated solutions that wasn't fully working as intended.

To use PureMVC, you have to extend a Singleton (Facade), which is the entry point of the framework. This is working only if you don't use the Facade class (the super Singleton) before using the subclass, otherwise you get an error, as the super singleton has already been instantiated.

Well this might be a simple solution but not working in my case.

First of all, they are a lot of solutions to correctly "lock" a Singleton, because in AS3, private constructor doesn't exist. Some of them have turn around, that you can solve with a bit more code, but the solution I prefer is instantiate the Singleton out of the constructor and method:

Actionscript:
  1. private static var _instance:Singleton = new Singleton();

So, if I use the super singleton with a Singleton.getInstance(), and then use the subclass with a SingletonExtended.getInstance(), this will throw an error as when the SingletonExtended is called, the Singleton is called as well and has already been instantiated.

The solution I found is compare the super class name with a static class name, basically you can't use the keyword "this" when you declare a variable, but using "super" will return the same result (well that's odd but it is what I saw):

Actionscript:
  1. private static var _className:String = getQualifiedClassName(super);

And then compare it with the super classname in the Singleton constructor:

Actionscript:
  1. if (_instance != null && getQualifiedSuperclassName(this) != _className) throw new Error

if I trace(_className + " - " + getQualifiedSuperclassName(this)) in the Singleton constructor:

- when I use the Singleton class, I get: "null - Object"
- when I use the SingletonExtended class, I get: "Singleton - Singleton", meaning the constructor has been called from a subclass.

Until now, it is working pretty well, I can use:

Actionscript:
  1. Singleton.getInstance().singletonValue
  2. SingletonExtended.getInstance().singletonValue
  3. SingletonExtended.getInstance().singletonExtendedValue

But we're not completely done. We can access to our two Singleton... but wait, "two Singleton", is that possible?

In fact, it is completely possible and it is even a problem. Let's say I have a undefined value in Singleton, like:

Actionscript:
  1. private var _myValueNotInitialized:String;

And then you have a public method that is setting a value to this variable:

Actionscript:
  1. public function initializeMyValue():void {
  2.     _myValueNotInitialized = "I am initialized";
  3. }

You can now use:

Actionscript:
  1. Singleton.getInstance().initializeMyValue();
  2. or
  3. SingletonExtended.getInstance().initializeMyValue();

But here is the problem: you still have 2 instances. One in Singleton and the other in SingletonExtended. If you use:
Singleton.getInstance().initializeMyValue();
and trace:
SingletonExtended.getInstance().myValueNotInitialized
you will get null, which is normal.

This doesn't make a lot of sense for a Singleton, does it?

The solution I found is updating the Singleton instance with the SingletonExtended one.

In the Singleton, I'm now able to update the instance:

Actionscript:
  1. public function updateInstance(instance:Singleton):void {
  2.     if (instance != null && instance is Singleton) _instance = instance;
  3.     else throw new Error("Incorrect Singleton update");
  4. }

And in the subclass SingletonExtended, I change the getInstance method:

Actionscript:
  1. public static function getInstance():SingletonExtended {
  2.     Singleton.getInstance().updateInstance(_instance);
  3.     return _instance;
  4. }

This is doing the job I needed, a fully Extended Singleton with no errors accessing the super or he subclass.

I tried to break it, but if it is possible, I didn't find the hole. And if you have a better solution, I'd be very happy to see it.

You can download the source by clicking here, or see the classes below.

The main class:

Actionscript:
  1. package {
  2.    
  3.     import flash.display.Sprite;
  4.    
  5.     /**
  6.      * <b>Author:</b> Romuald Quantin - <a href="http://www.soundstep.com/" target="_blank">www.soundstep.com</a><br />
  7.      * <b>Class version:</b> 1.0<br />
  8.      * <b>Actionscript version:</b> 3.0<br />
  9.      * <b>Date:</b> 11-2008<br />
  10.      */
  11.     
  12.     public class Main extends Sprite {
  13.        
  14.         //------------------------------------
  15.         // private properties
  16.         //------------------------------------
  17.        
  18.         //------------------------------------
  19.         // public properties
  20.         //------------------------------------
  21.        
  22.         //------------------------------------
  23.         // constructor
  24.         //------------------------------------
  25.        
  26.         public function Main() {
  27.            
  28.             trace("--- public properties ---");
  29.             trace(Singleton.getInstance().singletonValue + ">>> from Singleton");
  30.             trace(SingletonExtended.getInstance().singletonValue + ">>> from SingletonExtended");
  31.             trace(SingletonExtended.getInstance().singletonExtendedValue + ">>> from SingletonExtended");
  32.             trace(Singleton.getInstance().singletonValue + ">>> from Singleton");
  33.            
  34.             trace("--- access to public methods ---");
  35.             trace(Singleton.getInstance().publicSingletonMethod() + ">>> from Singleton");
  36.             trace(SingletonExtended.getInstance().publicSingletonMethod() + ">>> from SingletonExtended");
  37.             trace(SingletonExtended.getInstance().publicSingletonExtendedMethod() + ">>> from SingletonExtended");
  38.            
  39.             trace("--- access to private methods ---");
  40.             trace(Singleton.getInstance().accessPrivateSingletonMethod() + ">>> from Singleton");
  41.             trace(SingletonExtended.getInstance().accessPrivateSingletonMethod() + ">>> from SingletonExtended");
  42.             trace(SingletonExtended.getInstance().accessPrivateSingletonExtendedMethod() + ">>> from SingletonExtended");
  43.            
  44.             trace("--- access to protected and overriden methods ---");
  45.             trace(Singleton.getInstance().accessProtectedSingletonMethod() + ">>> from Singleton");
  46.             trace(SingletonExtended.getInstance().accessProtectedSingletonMethod() + ">>> from SingletonExtended");
  47.             trace(SingletonExtended.getInstance().accessOverridenSingletonExtendedMethod() + ">>> from SingletonExtended");
  48.            
  49.             trace("--- value not initialized ---");
  50.             trace("before = ", Singleton.getInstance().myValueNotInitialized);
  51.             Singleton.getInstance().initializeMyValue(); // or SingletonExtended.getInstance().initializeMyValue();
  52.             trace("after = ", Singleton.getInstance().myValueNotInitialized);
  53.            
  54.             // this will generate errors
  55.             // as you can't instantiate twice a Singleton or a sublass of Singleton
  56.            
  57.             //var s1:Singleton = new Singleton();
  58.             //var s2:SingletonExtended = new SingletonExtended();
  59.            
  60.         }
  61.        
  62.         //
  63.         // PRIVATE, PROTECTED
  64.         //________________________________________________________________________________________________
  65.        
  66.         //
  67.         // PUBLIC
  68.         //________________________________________________________________________________________________
  69.        
  70.     }
  71. }

The Singleton class:

Actionscript:
  1. package {
  2.  
  3.     import flash.utils.getQualifiedClassName;
  4.     import flash.utils.getQualifiedSuperclassName;
  5.  
  6.     /**
  7.      * <b>Author:</b> Romuald Quantin - <a href="http://www.soundstep.com/" target="_blank">www.soundstep.com</a><br />
  8.      * <b>Class version:</b> 1.0<br />
  9.      * <b>Actionscript version:</b> 3.0<br />
  10.      * <b>Date:</b> 11-2008<br />
  11.      */
  12.     
  13.     public class Singleton {
  14.        
  15.         //------------------------------------
  16.         // private properties
  17.         //------------------------------------
  18.        
  19.         private static var _instance:Singleton = new Singleton();
  20.         private static var _className:String = getQualifiedClassName(super);
  21.        
  22.         private var _myValueNotInitialized:String;
  23.        
  24.         //------------------------------------
  25.         // public properties
  26.         //------------------------------------
  27.        
  28.         public var singletonValue:String = "Singleton value";
  29.        
  30.         //------------------------------------
  31.         // constructor
  32.         //------------------------------------
  33.        
  34.         public function Singleton() {
  35.             if (_instance != null && getQualifiedSuperclassName(this) != _className) throw new Error("Singleton is obviously... Singleton.");
  36.         }
  37.        
  38.         //
  39.         // PRIVATE, PROTECTED
  40.         //________________________________________________________________________________________________
  41.        
  42.         private function privateSingletonMethod():String {
  43.             return "privateSingletonMethod";
  44.         }
  45.        
  46.         protected function protectedSingletonMethod():String {
  47.             return "protectedSingletonMethod";
  48.         }
  49.        
  50.         //
  51.         // PUBLIC
  52.         //________________________________________________________________________________________________
  53.        
  54.         public function initializeMyValue():void {
  55.             _myValueNotInitialized = "I am initialized";
  56.         }
  57.        
  58.         public function updateInstance(instance:Singleton):void {
  59.             if (instance != null && instance is Singleton) _instance = instance;
  60.             else throw new Error("Incorrect Singleton update");
  61.         }
  62.  
  63.         public static function getInstance():Singleton {
  64.             return _instance;
  65.         }
  66.        
  67.         public function publicSingletonMethod():String {
  68.             return "publicSingletonMethod value";
  69.         }
  70.        
  71.         public function accessPrivateSingletonMethod():String {
  72.             return privateSingletonMethod();
  73.         }
  74.        
  75.         public function accessProtectedSingletonMethod():String {
  76.             return protectedSingletonMethod();
  77.         }
  78.        
  79.         public function get myValueNotInitialized():String {
  80.             return _myValueNotInitialized;
  81.         }
  82.     }
  83. }

The SingletonExtended class:

Actionscript:
  1. package {
  2.  
  3.     /**
  4.      * <b>Author:</b> Romuald Quantin - <a href="http://www.soundstep.com/" target="_blank">www.soundstep.com</a><br />
  5.      * <b>Class version:</b> 1.0<br />
  6.      * <b>Actionscript version:</b> 3.0<br />
  7.      * <b>Date:</b> 11-2008<br />
  8.      */
  9.     
  10.     public class SingletonExtended extends Singleton {
  11.        
  12.         //------------------------------------
  13.         // private properties
  14.         //------------------------------------
  15.        
  16.         private static var _instance:SingletonExtended = new SingletonExtended();
  17.        
  18.         //------------------------------------
  19.         // public properties
  20.         //------------------------------------
  21.        
  22.         public var singletonExtendedValue:String = "SingletonExtended value";
  23.        
  24.         //------------------------------------
  25.         // constructor
  26.         //------------------------------------
  27.        
  28.         public function SingletonExtended() {
  29.             if (_instance != null) throw new Error("SingletonExtended is obviously also... Singleton.");
  30.         }
  31.        
  32.         //
  33.         // PRIVATE, PROTECTED
  34.         //________________________________________________________________________________________________
  35.        
  36.         private function privateSingletonExtendedMethod():String {
  37.             return "privateSingletonExtendedMethod";
  38.         }
  39.        
  40.         override protected function protectedSingletonMethod():String {
  41.             return "protectedSingletonMethod overriden in SingletonExtended, value in super.protectedSingletonMethod(): " + super.protectedSingletonMethod();
  42.         }
  43.        
  44.         //
  45.         // PUBLIC
  46.         //________________________________________________________________________________________________
  47.        
  48.         public static function getInstance():SingletonExtended {
  49.             Singleton.getInstance().updateInstance(_instance);
  50.             return _instance;
  51.         }
  52.        
  53.         public function publicSingletonExtendedMethod():String {
  54.             return "publicSingletonExtendedMethod value";
  55.         }
  56.        
  57.         public function accessPrivateSingletonExtendedMethod():String {
  58.             return privateSingletonExtendedMethod();
  59.         }
  60.        
  61.         public function accessOverridenSingletonExtendedMethod():String {
  62.             return protectedSingletonMethod();
  63.         }
  64.    
  65.     }
  66. }

Comments No Comments »

I've added a little feature to the FPS class, you still can hide the bar by clicking on it and you can show the bar again by typing "fps". I've also slightly changed the way I show the values.

You can find the source if you click here.

Comments 1 Comment »

Hi everyone,

Before going on holiday, here is a BaseUI major release :)

Demo, source and code are at the end of the post or in the BaseUI main Page.

It means code written for the previous might not work for this version (even is there isn’t any major change in the structure, some internal code has been changed). If you want to update your code with this version, unless you were using the version 1, it won’t take a long time to adapt it.

I won’t explain in details the basics of BaseUI, you’ll find complete explanations in the tutorials in the BaseUI main page.

Before we could say that BaseUI was an assets manager, now it is becoming a real layout manager.

The two main classes BaseUI and ElementUI allow you to handle assets positioning by using properties on your DisplayObject like top, bottom, width, percentage width, horizontal center and so on, to make them working with the resize event (when the browser is resized by the user). It makes you able to handle liquid layouts, but also works with fixed layouts.

In the first version, BaseUI has been built mainly to work on the stage. It is working now from the version 2 with any reference, stage or another DisplayObject (see properties like onstage and reference).

As I’m also a Flex user and I’ve started to build layout for Flash taking example of the Flex framework.

In this version you’ll find a canvas, a horizontal box, a vertical box and a tile. Those new classes will be found in a layout package: CanvasUI, HBoxUI, VBoxUI and TileUI. All kind of components you can find in the Flex framework, even the name is very close so you don’t get lost with alien class name. Let’s keep things simple.

Before we start on the new classes, let’s see what the changes in BaseUI and ElementUI are. Well, almost nothing changed in appearance. Bugs have been solved and few methods and properties added.

BaseUI

Method: contains
Return true of false if the BaseUI instance already contains the DisplayObject, like you can find in a DisplayObjectContainer such as Sprite or MovieClip.

Property: autoRefresh (default true)
This is a global setting, meaning all the ElementUI created by adding DisplayObject to the BaseUI instance will get the same setting, it can be overridden in each ElementUI instance. By default, when you set a property on an ElementUI instance, the size and positions of the DisplayObject are automatically calculated and “refreshed”. Using autoRefresh set to false, you’ll have to refresh yourself the element by using the refresh methods. This applies only for setting properties, the elements will still be automatically “refreshed” when the Event.RESIZE is triggered. This property is useful if you have a lot of DisplayObject and you don’t want to execute some useless code.

ElementUI

Property: autoRefresh (default true)
See BaseUI autoRefresh description above.

Properties: forceReferenceHeight and forceReferenceWidth
BaseUI is using width and height to set the position of the DisplayObject, sometimes the size can be disturbed by mask or components. They are some properties to help you handle these problems, for example: useInitialSize or bypassSize. I’ve added these two properties and they are the strongest reference that will be used for calculate a new position.

Other layouts will be built, at least a Grid and another Canvas to handle overlapping. I'm basically waiting the official Flash Player 10 release as it has a nice text layout manager!

I’ll write a complete tutorial in the future, let’s see the layouts classes in details.

HBoxUI, VBoxUI and TileUI are subclasses of CanvasUI that is a subclass of MovieClip.

A canvas is containing:
- a Wrapper to handle the size of the canvas
- a Sprite container containing the children added in the canvas
- a Mask to hide the content that is outside of the canvas (optional)
- a Scrollpane component to handle scrollbars if the content is bigger than the canvas (optional)

CanvasUI

The main meaning of a canvas is having an area you can resize without having the content resized. As in Flex, the canvas is an absolute layout and children can overlap. It will be possible to handle some behaviors impossible without. It is also the easiest way to have a centered fixed area in the browser and easily handle ElementUI inside.

To create a canvas:

Actionscript:
  1. var canvas:CanvasUI = new CanvasUI();

A canvas constructor can take 4 optional parameters: width, height, layoutScroll, layoutMask. By default, CanvasUI build a mask to show only the content within the size specified and creates scrollbars (scrollpane instance) if the content is bigger than the size specified. If you don’t need the mask or the scrollbar, just set them to false when you create the instance. If you set the layoutScroll to false, you don’t need a scrollpane component in the flash library (or SWC for Flex SDK user), it will not be imported or created. For example:

Actionscript:
  1. var canvas:CanvasUI = new CanvasUI(200, 200, false, false);

A canvas has a background color and alpha (default is 0), you can set those values if you want to see your canvas:

Actionscript:
  1. canvas.canvasColor = 0xFF0000;
  2. canvas.canvasAlpha = 0.5;

You can use all the ElementUI properties, for example: top, bottom, width, ratio, etc… straight on the canvas. The only difference, unlike ElementUI, the width and height percentage is set with others properties (percentWidth and percentHeight). For example:

Actionscript:
  1. canvas.horizontalCenter = 0;
  2. canvas.percentWidth = “80%”; // or “80” or 80
  3. canvas.bottom = 20;
  4. canvas.height = 300;

A canvas has an internal BaseUI instance (for wrapper, mask and scrollpane) and another for the children. The internal BaseUI instance has the property autoRefresh set to false to keep good performance. It means when you are done setting the properties for the canvas, you must refresh it (this is only for the canvas, you don’t need to do that after adding children):

Actionscript:
  1. canvas.refresh();

You can add children as you would do with a Sprite or other DisplayObjectContainer using the addChild method. You can also use addChildUI to add a child and an ElementUI instance will be created. You can also set ElementUI properties on the children, for example:

Actionscript:
  1. var el:ElementUI = canvas.addChildUI(mySprite);
  2. el.ratio = ElementUI.RATIO_IN;
  3. el.properties = {top:10, bottom:10, left:10, right:10};

You have some methods to get or remove the ElementUI (see documentation):

Actionscript:
  1. var el:ElementUI = canvas.getChildUI(mySprite);
  2. canvas.getChildUI(mySprite).bottom = 20;
  3. canvas.getChildUIByName("mySprite").right = 20;
  4. canvas.removeChildUI(mySprite);

CanvasUI is a mix between inheritance and polymorphism to make behaviors working properly. Most of the MovieClip methods and properties are accessible from the canvas instance. You might find some missing or not working properly, testing all methods and properties between DisplayObjectContainer and MovieClip is a hudge work as some are applied on the wrapper, others on the canvas and others on the container. If you’ve got a problem, you can access to the internal elements through properties (see the documentation).

HBoxUI, VboxUI and TileUI

These layouts are subclassing the CanvasUI and you’re not free to set the position of the children, they are calculated internally. You’ll find some properties common in the Flex layouts.

HBox horizontally lays out its children one by one, you have access to properties like horizontalGap, alignChildren, verticalCenterChildren and padding. Here is an example:

Actionscript:
  1. var hbox:HBoxUI = new HBoxUI();
  2. addChild(hbox);
  3. hbox.horizontalGap = 5;
  4. hbox.alignChildren = HBoxUI.ALIGN_CENTER;
  5. hbox.verticalCenterChildren = 40;
  6. hbox.padding = new Padding(10, 10, 25, 10);
  7. hbox.name = "hbox";
  8. hbox.reference = this;
  9. hbox.percentWidth = "50%";
  10. hbox.height = 200;
  11. hbox.right = 20;
  12. hbox.bottom = 20;
  13. hbox.canvasAlpha = .4;
  14. hbox.refresh();
  15. hbox.addChild(mySprite1);
  16. hbox.addChild(mySprite2);
  17. hbox.addChild(mySprite3);

VBox vertically lays out its children one by one, you have access to properties like verticalGap, alignChildren, horizontalCenterChildren and padding. Here is an example:

Actionscript:
  1. var vbox:VBoxUI = new VBoxUI();
  2. addChildUI(vbox);
  3. vbox.alignChildren = VBoxUI.ALIGN_CENTER;
  4. vbox.horizontalCenterChildren = 40;
  5. vbox.padding = new Padding(10, 25, 10, 10);
  6. vbox.name = "vbox";
  7. vbox.reference = this;
  8. vbox.percentWidth = "50%";
  9. vbox.height = 200;
  10. vbox.right = 20;
  11. vbox.bottom = 20;
  12. vbox.canvasAlpha = .4;
  13. vbox.refresh();
  14. vbox.addChild(mySprite1);
  15. vbox.addChild(mySprite2);
  16. vbox.addChild(mySprite3);

TileUI lays out its children in a grid of equal-sized cells. You can set additional properties like horizontalGap, verticalGap, direction and padding. Here is an example:

Actionscript: