Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

Introduction to the Dojo toolkit, Part 1: Setup, core, and widgets

Object-oriented JavaScript programming for Java developers

  • Print
  • Feedback

Page 5 of 6

Object-oriented JavaScript

One of the lesser-known facts about JavaScript is that it is an object-oriented language. However, it is a prototype-based object-oriented language that doesn't have the same structure as class-based languages such as Java. This can be a hard adjustment for new JavaScript programmers. Dojo provides functionality to simulate class-based object-oriented concepts such as declaring classes, constructors, and inheritance. In the background, it takes care of things like prototyping, inheritance, and various procedures that JavaScript requires. In the next sections I'll introduce you to Dojo's support for object-oriented programming with JavaScript.

Working with classes

Dojo provides a dojo.declare() method that you should use to declare a new class. It accepts the following arguments:

  • A string representing the name of the class that you want to declare.
  • The name of the superclass or array of names of the superclasses that you want this class to inherit from. (I'll talk more about multiple inheritance later.)
  • A hashmap of properties for the class. The properties represent both instance variables and member function of this class.

Listing 2, for example, declares a custom.javaworld.Worker class:

Listing 2. Declaring a class

dojo.declare("custom.javaworld.Worker",null,{
    firstName: "",
    lastName: "",
    work: function(){
        console.log("Working");
    }
});
var johnDoe = new custom.javaworld.Worker();
johnDoe.work();
johnDoe.lastName ="Doe";
console.log("Last Name " + johnDoePerson.lastName);

In Listing 2, the dojo.declare() method's first argument is custom.javaworld.Worker -- the name of the class we want to declare. The method's second argument is null because we don't want to inherit this class from any other class. The third argument is a hashmap, in which work is the property's name and its value is a function. We thereby define a work() member function for the Worker class.

Once the custom.javaworld.Worker class is declared, you can create a new object instance of it by calling new custom.javaworld.Worker(). Then you can start calling the new object's methods or assign values to its member variables.

Constructors

A constructor allows you to initialize every object of a class by executing code whenever a new instance of the class is created. Listing 3 changes our custom.javaworld.Worker class to add a constructor.

Listing 3. Adding a constructor

dojo.declare("custom.javaworld.Worker",null,{
    firstName: "",
    lastName: "",
    constructor: function(fName, lName){
        console.debug("Constructor of com.javaworld.Worker called");
        this.firstName = fName;
        this.lastName = lName;
    },
    work: function(){
        console.log("Working");
    }
});

var johnDoe = new com.javaworld.Worker("John","Doe");
console.log("First Name " + johnDoePerson.firstName);
console.log("Last Name " + johnDoePerson.lastName);

As you can see, we made one change in the custom.javaworld.Worker class to add a constructor member function. The constructor member function is special. It gets called whenever you create new instance of the class using the JavaScript's new operator. The constructor takes two arguments -- fName and lName -- and assigns these value to the member variables, which you access by using the this operator inside the class.

Inheritance

The ability to extend other classes is one of the basic features of object-oriented programming. Dojo handles all the requirements for setting up an inheritance chain. For example, when you create an instance of a class, Dojo calls the constructor of its superclass before calling constructor of the child class. Also, if you add a method to the child class with same name as that of the superclass, then the method in the child class overrides the method in the superclass.

Listing 4 creates a custom.javaworld.ITWorker class that extends custom.javaworld.Worker.

Listing 4. Extending a class

dojo.declare("custom.javaworld.ITWorker",custom.javaworld.Worker,{
    constructor: function(fName, lName){
        console.debug("Constructor of com.javaworld.ITWorker");
    },
    work: function(){
        this.inherited(arguments);
        console.log("Writing Code");
    }
});
var johnDoe = new com.javaworld.ITWorker("John","Doe");
johnDoe.work();

Because we want ITWorker to extend the Worker class, Listing 4 passes the custom.javaworld.Worker class as the second argument when declaring the ITWorker class. Now when you create a new instance of ITWorker using the new operator, Dojo first invokes the constructor of Worker class. Also, the ITWorker class's work() method overrides the Worker class's work() method.

Suppose you need to invoke the overridden method of superclass first and then add some functionality in the child class method. In that case then you can use the.inherited() construct to invoke an inherited method of the superclass. In Listing 4, when you call the ITWorker class's work() method, it first invokes the Worker class's work() method, which prints "Working" on the console then prints "Writing Code" on the console.

Multiple inheritance

Dojo allows a class to inherit from multiple classes. Listing 5 creates a PartTimeMusician class that inherits from both ITWorker and Musician.

Listing 5. Inheriting from multiple classes

dojo.declare("com.javaworld.Musician",null,{
    constructor: function(fName, lName){
        console.debug("Constructor of com.javaworld.Musician");
    },
    playMusic: function(){
        console.log("Playing Music");
    }
});
dojo.declare("com.javaworld.PartTimeMusician",[com.javaworld.ITWorker,com.javaworld.Musician],{
    constructor: function(fName, lName){
        console.debug("Constructor of com.javaworld.PartTimeMusician");
    }
});
var johnDoe = new com.javaworld.PartTimeMusician("John","Doe");
johnDoe.work();
johnDoe.playMusic();

In Listing 5, we pass an array of ITWorker and Musician as the second argument to the dojo.declare() method while declaring the PartTimeMusician class. Now when you execute this code it will generate output like this:

Constructor of com.javaworld.Worker called
Constructor of com.javaworld.ITWorker
Constructor of com.javaworld.Musician
Constructor of com.javaworld.PartTimeMusician
Working
Writing Code
Playing Music

As you can see, the constructor of the Worker class, which is the parent of the ITWorker class, is invoked first, followed by the constructor of ITWorker. The constructor of ITWorker is called before Musician's constructor because, while declaring the PartTimeMusician class, we passed an array of superclasses in which ITWorker was the first argument and Musician was the second argument.

  • Print
  • Feedback

Resources

More from JavaWorld