Click here to Skip to main content
15,867,686 members
Articles / Programming Languages / Javascript
Article

Raiya in Humax v0.3: Extending your JavaScript Classes like Ruby's Mixin

Rate me:
Please Sign up or sign in to vote.
0.00/5 (No votes)
2 Dec 2008CC (ASA 2.5)3 min read 13K   27   3  
Another way to achieve class extensions without using inheritence

Introduction to Raiya

Humax JavaScript Framework introduces "Raiya" (means water that is the most qualifed resource for mixing the other resources) which enables programmer to define generic functionalities on raiya, later it can be plugged into any Humax compatible class. When this happen, all the plugged raiya's methods are immediately available as methods in the class as well. In this way, you can extend a class without affecting its core functionality.

Raiya was inspired by Ruby's Mixin. Humax allows you to extend your JavaScript classes with more flexible and systematic way without using typical Inheritence. This will provide you a new way to design your applications.

There are three ways you can build a raiya:

  • Native cohesive raiya. These types of raiyas are developed for a family of classes those are owned and understand by the raiya developer itself. In this case, the raiya developer knows the private members of the target base class (mostly base class) and uses these members directly in the raiya.

    Native Cohesive Raiya

    Figure 1: Native Cohesive Raiya

  • Native closed raiya. These types of raiyas are developed for providing extensibility to the classes from third party. They know their public methods and uses that methods in the raiya.

    Native Closed Raiya

    Figure 2: Native Closed Raiya

  • Self contained raiya. These types of raiyas are developed without targeting any classes. These raiyas are implemented for a generic functionality. Later any required classes can plug these raiyas into them by RaiyaFieldMapFacet.

    Self Contained Raiya

    Figure 3: Self Contained Raiya

Developing Native Cohesive Raiya

Let us consider the following Customer class.

JavaScript
$class("HxTest.Customer",
{
    _name : null,
    _city : null,
    
    initialize : function(name, city)
    {
        this._name = name;
        this._city = city;        
    },
    
    getName : function() {return this._name;},
    getCity : function() {return this._city;}
});

Let us consider the following collection class which helps to manage Customer specific collection.

JavaScript
$class("HxTest.CustomerCollection",
{
    _customers : null,
    
    initialize : function()
    {
        this._customers = [];
    },
    
    add : function(customer)
    {
        if(customer.getType().is("HxTest.Customer"))
            this._customers.push(customer);
    },
    
    getCustomers : function() {return this._customers;}
});

We can add new Customer class instance to the collection and later we can iterate through collection. See the following code snippets:

JavaScript
var customerCollection = new HxTest.CustomerCollection();

...

var customer = new HxTest.Customer("M Sheik Uduman Ali", "Chennai");                
customerCollection.add(customer);

...

var arrayCust = customerCollection.getCustomers();
for(var i = 0; i < arrayCust.length; i++)
{
    display(arrayCust[i].getName(), arrayCust[i].getCity());
}

Necessary for Raiya

Assume that there is a necessary to provide a "city" based filter to fetch the customers only from the given city. You add new public method in the CustomerCollection for this functionality. Consumer of this class should aware and use this method. However, in real case, adding more and more generic or non-generic functionality to the classes makes the system complex and sometime results repeated implementation for example the "filter" functionality in CustomerCollection. The object oriented approach does not help this scenario none other than derive a new class from the current one or implement it on the class itself. If the class we need to add functionality is actually developed by some third party, self implementation does not help. Since, multiple inheritence is strictly not recommended in the programming world, Humax lets you achieve this using "Raiya".

$raiya() allows to define raiya. See the following code.

JavaScript
$raiya("HxTest.CityFilterRaiya",
{
    filter : function(cityName)
    {
        var filteredCollection = new HxTest.CustomerCollection();
        for(var i = 0; i < this._customers.length; i++)
        {
            if(this._customers[i].getCity() == cityName)
                filteredCollection.add(this._customers[i]);
        }
        return filteredCollection;
    }
});

The first argument should be raiya name and second argument should be the methods declaration. Both these are mandatory to define a raiya and no other things required. Here, CityFilterRaiya is a native cohesive raiya since it directly handles the CustomerCollection's private member this._customers.

Applying Raiya

Humax compatiable classes now have a method include for plug-in a raiya on it. The following code explains this.

JavaScript
HxTest.CustomerCollection.include(HxTest.CityFilterRaiya);

Now we can use the filter function in the instances of CustomerCollection.

JavaScript
customerCollection.filter("Chennai");

The above code returns CustomerCollection of "Chennai" based customers.

Using Self Contained Raiya

Assume that you need HxTest.CityFilterRaiya for CustomerCollection, however it was developed by third party and it is not good practise to use their private properties. In this case, HxTest.CityFilterRaiya is considered as self-contained raiya and you need a bridge to map your class properties with the properties exposed by HxTest.CityFilterRaiya. RaiyaFieldMapFacet acts as the bridge for any of your class with self-contained raiya.

You are going to use the following raiya.

JavaScript
$raiya("HxTest.SelfContainedCityFilterRaiya",
{
    filter : function(cityName)
    {
        var filteredCollection = new Array();
        for(var i = 0; i < this._collection.length; i++)
        {
            if(this._collection[i].getCity() == cityName)
                filteredCollection.push(this._collection[i]);
        }
        return filteredCollection;
    }
});

In order to use this raiya in CustomerCollection, you create a field map facet as

JavaScript
var fieldMapRaiya = new Humax.RaiyaFieldMapFacet("HxTest.SelfContainedCityFilterRaiya",
                {"_collection": "_customers"});

The first argument tells for which raiya this map is going to apply. Second argument gives the actual map list in JSON in the format <RaiyaFieldName>:<TargetClassFieldName>.

The next step is to apply this facet to CustomerCollection. Then you can include SelfContainedCityFilterRaiya into CustomerCollection.

JavaScript
HxTest.CustomerCollection.apply(fieldMapRaiya);            
HxTest.CustomerCollection.include(HxTest.SelfContainedCityFilterRaiya);

Important Note. In SelfContainedCityFilterRaiya's filter() method, there is no systematic way to specify map for getCity(). In future, Humax will resolve this issue.

License

This article, along with any associated source code and files, is licensed under The Creative Commons Attribution-ShareAlike 2.5 License


Written By
Architect Aditi
India India
Working as Architect for Aditi, Chennai, India.

My Website: www.udooz.net

My Blog: www.udooz.net/blog

Comments and Discussions

 
-- There are no messages in this forum --