From OOP to ActionScript and back to Flex

This tutorials explores object-oriented programming principles in some of the technologies behind the Flex framework. We will first examine how to implement a custom datatype in Actionscript 3, then we'll delve into Flex intricacies as we turn our custom datatype into a loosely coupled component, ready for deployment as a SWC file.

Switch styles

Contents:

1. Introduction : the case for a currency datatype
2. Fixed properties
3. Getter and setter methods
4. From an ActionScript class to a Flex component
5. Conclusion
6. Discuss this article

Note

This tutorial doesn't rely on previous knowledge of Flex or Actionscript, but it does require familiarity with Object-Oriented principles.

Source code

You can download the source code accompanying this tutorial here.

1. Introduction : the case for a currency datatype

In Actionscript, the three fundamental datatypes are Null, void, and Object. The Object datatype encompasses all the built-in classes such as Date, Boolean, Array, and so forth, as well as the custom datatypes that we implement when writing classes or interfaces.

Note

All classes that don't declare an explicit base class extend the built-in Object class. Actionscript 3 is the first version to offer class-based inheritance as opposed to the prototype-based inheritance found in previous versions of the language. Both methodologies actually coexist in Actionscript 3, but we will stick to the class-based inheritance mechanism, as it is the preferred method in terms of safety, predictability, correctness and efficiency.

The same way we instantiate the built-in datatypes applies to our custom ones.

var today = new Date();
var members = new Array();
...
var dollar = new Currency();

2. Fixed properties

This is quite straightforward, but what properties should we expect from the Currency datatype? Well, we might want to define fixed properties such as the name of the currency, its symbol, its ISO 4217 code (the standardized abbreviation used in the finance world), and maybe even its exchange rate compared to a base currency. Let's proceed in steps and limit ourselves for now to fixed properties. Consider this new object definition, but this time with constructor arguments:

var dollar = new Currency("USD", "$");

In the last example, the object has properties assigned to it at creation time, which will be accessible as such:

dollar.isoCode
USD

Or:

dollar.symbol
$

How does this behavior come to effect? Simply, by writing the class that defines the Currency datatype. That class would look something like this:

	public class Currency {
	
		private var isoCode;
		private var symbol;
			
		public function Currency(isoCode,symbol){
		
			this.isoCode = isoCode;
			this.symbol = symbol;

	}

}

However, the compiler in Flex runs by default in strict mode, enforcing strong typing, another late addition the language feature-set as it evolves and matures. The benefit of compile-time checks for type constraint violations is to catch errors early on. Hence, our code will look like this:


	public class Currency {
	
       private var isoCode:String;
       private var symbol:String;
	   

             public function Currency(isoCode:String,symbol:String){
			 
                        this.isoCode = isoCode;
                        this.symbol = symbol ;
						
                        }

   }

Note

Note that when we instantiate the object, we also use type annotation. Compare the following code with the previous one:

	var dollar:Currency = new Currency("USD", "$");

So now we have a Currency datatype that we can use in our program. We can define any number of currencies.

var pound:Currency = new Currency("GBP","£");
var shekel:Currency = new Currency("ILS","₪");

3. Getter and setter methods

Until now our class defines fixed properties, and no methods whatsoever. Why not extend our Currency datatype so as to include a property called exchange rate, which will hold the current exchange rate of that currency compared to a base currency? Additionally, we want that exchange rate to be live, so instead of hard-wiring it into a variable, or fetching it from a static source, we are going to consume a web service providing up-to-date exchange rates of major currencies, and the result will be fed into that property.

The functionality behind our exchange rate fetching mechanism will be packed in a method that gets called each time we get or set the rate property. This is a scenario that begs the usage of getters and setters. Our exchange rate will thus be a pseudo-variable: it does not exist as such (as a variable), but can be used as though it did. Let's see how this adds up with our previous class:

public class Currency{


//These properties are the same as before


	public var isoCode:String;
	public var symbol:String;
	
// This is our internal variable    


	private var _rate:Number;
	
// This is our base currency against which we are going to compare exchange rates   


	public var baseCurrency:String;


// Here comes our constructor 


	public function Currency(isoCode:String,symbol:String) 
   	{
			this.isoCode = isoCode;
			this.symbol = symbol;
			this._rate = 0;
			this.baseCurrency = isoCode;
		}
		

//This is our getter


	public function get rate():Number {
		return _rate;
	}


//This is our setter


	public function set rate(number:Number):void    
   	{
		_rate = number;
		var ws:WebService = new WebService();
		ws.wsdl = "http://www.webservicex.net/CurrencyConvertor.asmx?WSDL";
		ws.ConversionRate.addEventListener("result", resultHandler);
		ws.loadWSDL();
	    ws.ConversionRate(baseCurrency, isoCode);
		}
	
	public function resultHandler (event:ResultEvent):void
    	{
	
    		_rate = event.result as Number;
		}
}

As we can see, the setter is doing all the work here by using the built-in WebService class. In the source code that you might have downloaded you will find the import statements that make it possible to use this and related classes. The web service we are calling at www.webservicex.net exposes a public method called ConversionRate. We attach an event to that method so that when data comes in, we update our _rate property.

Getters and setters are also known as accessor methods and mutator methods. Don't forget to use internal properties that mask the name of these methods, as in _rate and rate, or you will expose yourself to stack overflow errors. Another important and related note is that when a set method is called it always invokes its corresponding get method and returns the get method's return value, allowing the program to use the new value immediately after setting it. For this reason, get methods should never perform tasks beyond those required to retrieve their internal variable value. So now you know why the fetching mechanism is packed in the setter, and not the getter, as one might have expected. Note also that by setting a value to our rate property before calling the remote method ensures that if that method fails, the property still holds a default value.

4. From an ActionScript class to a Flex component

Our Currency datatype now boasts nifty features, so what's wrong with it? Nothing, really, but it hardly relates to the Flex framework, does it? Flex is all about visual components that respond to internal events and changes on the screen. In our example, an internal event of interest would be when the exchange rate property of our currency object gets updated. In other words, we want that property to be bindable, so that all instances on display always reflect its current value. We might also want to instantiate our Currency object according to Flex standard practice, that is, with MXML statements. In other words, we want to be able to say:

<component:Currency id="dollar" isoCode="USD" baseCurrency="ILS" rate="4"/>

Instead of:

var dollar = new Currency("USD", "$");
dollar.rate = 5;

In short, we need to transform our ActionScript class into what is known in Flex as a custom component. Flex applications often have complex architectures composed of multiple files: MXML, ActionScript and CSS. But we will see how to write our component as a loosely coupled one, so as to eliminate code dependencies and achieve true reusability. This will allow us to deploy our Currency datatype as a SWC file, a black box that can be used cleanly and safely across projects, teams or organisations.

A loosely coupled component has a well-defined interface that specifies how to pass information to the component, and how the component passes back results to the application. The properties of a loosely coupled component are defined by using implicit accessors, the setter and getter methods we're already familiar with. The best practice for defining components that return information back to the main application is to design the component to dispatch an event that contains the return data. Hence, the first change in our new class will be to extend it with the built-in EventDispatcher class. This allows us to call the dispatchEvent() method in our resultHandler() method, which in turn is dispatched when the web service returns data for our exchange rate property. Our properties use the Bindable metadata tag linked to an event that we will call rateRefresh, allowing the Flex framework to make data binding work without further intervention. The Inspectable metadata tag for our private properties define an attribute that appears in the attribute hints and Tag inspector in Adobe Flex Builder.

Note

Flex Builder uses the public/protected/private/static modifiers plus the current scope to figure out what ActionScript code hints to show.

Let's look at our new class:

public class Currency extends EventDispatcher
       {
	[Inspectable]
	private var _rate:Number;
		
	[Inspectable]
	private var _isoCode:String;
		
	[Inspectable]
	private var _baseCurrency:String;
		
	[Inspectable]
	private var _symbol:String;

	
	public function Currency()
	   {
		}
	public function set isoCode(string:String):void
	   {
     _isoCode = string;
   	   }	

	public function get isoCode():String
       {
    return _isoCode;
   	 }

	public function set symbol(string:String):void
       {
        _symbol = string;
       }
	public function get symbol():String
       {
      return _symbol;
       }

	public function set baseCurrency(string:String):void
       {
          _baseCurrency = string;
       }
	public function get baseCurrency():String
       {
      return _baseCurrency;
       }
	public function set rate(number:Number):void
       {
      _rate = number;
      var ws:WebService = new WebService();
      ws.wsdl = "http://www.webservicex.net/CurrencyConvertor.asmx?WSDL";
      ws.ConversionRate.addEventListener("result", resultHandler);
      ws.loadWSDL();
      ws.ConversionRate(_baseCurrency, _isoCode);
       }
	[Bindable(event="rateRefresh")]
	public function get rate():Number
       {    
          return _rate;   
   }


	public function resultHandler (event:ResultEvent):void 
  {
         _rate = event.result as Number;          
         dispatchEvent(new Event("rateRefresh"));
      }
}	  

Note

To deploy this component as a self-contained SWC file, all we have to do is create a new library project in Flex Builder, include our Currency class as the source path in the project's properties, and finally, compile it.

In order to use the currency datatype in your projects, just copy the SWC file in your libs folder, and Flex Builder will find it automatically. If not, check in the properties of your project for the library build path setting.

Alternatively, you can study, edit or compile the source code of this project for your own purposes.

5. Conclusion

And with this we come to a close for this discussion. We went from pure OOP considerations to the wetter grounds of Flex, without getting too wet. Our Currency datatype packed in a Flex component is atypical, because ours is not a visual component, but a logical one. This allowed us to keep a safe distance from the innards of Flex. Sometimes, though, you'll be much closer to the plumbing that display programming implies. Fortunately, documentation resources are plentiful on the web, and thanks to the mature ActionScript 3, you'll be able to implement proven methodologies to solve most if not all design problems.

 

Note

This tutorial is free of charge. If you have found it useful and would like to reward the effort with a small donation, you're welcome to do so. Just click below.

6. Discuss this article

iso 9000 I positively venerate celebration of a mass your blog posts, a accumulation of essay is smashing.we have had to bookmark your site as well as allow to your feed.Your thesis looks lovely.Thanks for sharing.
iso 9001 It was a awe-inspiring post and it has a significant meaning and thanks for sharing the information.Would love to read your next post too......

Thanks

Regards:
iso 9001 It was a awe-inspiring post and it has a significant meaning and thanks for sharing the information.Would love to read your next post too......

Thanks

Regards:
Groodiare
Name or email

I am not a robot

Please note that once posted, your comment cannot be changed.


© Daniel Szmulewicz, 1996 - 2011

 

 

about | work | code | silly | cv
home | blog | contact | back