
Servoy Tutorial Photo Credit:
rob smith photography via Compfight
This is an object-oriented Servoy tutorial on how to use prototypal inheritance in Servoy. When you create a new object using a constructor function, the new object inherits the properties and functions from the constructor and the prototype. However, the real power in object-oriented programming comes from being able to clone new objects from existing objects, thereby inheriting the original object’s properties and functions. The new object can then be modified to suit our needs; we can add more properties, methods, and even use it as the object to clone new ones from again. By doing so, we can build up a hierarchy of objects that we can use to solve real-world programming challenges. In this article, we are going to take a look at how to do that.
First, lets take a reality check. You should already know the basics of how to work with objects from the “Object-Oriented Programming” and “Inheritance” articles I posted. If not, refer to the “Related Posts” section at the end of this article. You should feel comfortable with those two articles before you join me in taking it to the next level in this article.
Imagine for a moment that we are working on a project for a car dealership. We need to keep track of a variety of vehicles, of various types (cars, trucks, vans), makes, models, and colors.
Lets start out by creating a vehicle object using an object literal. For simplicity, we will just add a few properties that would be common for most vehicles, like name, make, color, mpg, and a function to return the object name (for demonstration purposes only). Obviously, in the real-world scenario, you would have many more properties and functions to represent the base vehicle.
1 2 3 4 5 6 7 8 9 10 11 12 13 | function Vehicle(){ var vehicle = { objName: 'Vehicle', name: 'unknown', make: 'unknown', color: 'unknown', mgp: 0, getObjName: function(){ return this.objName; } }; return vehicle; } |
Next, we will build a car object, since it is a type of vehicle that could differ from trucks and vans. We do this by first creating a new vehicle object using the Vehicle constructor function. Next, we use a special utility function called objectPlus, to which we pass the object we are cloning, in this case the vehicle. We overwrite the name property, add a new type property, and overwrite the getName function. By the way, we are not going to worry about whether a property should be here in the car object, or in the vehicle; we are just trying to learn something. In the getName function we introduce the JavaScript uber keyword, which refers to the “parent object” we are cloning, in this case, vehicle. After cloning and modifying the vehicle object, we return a car object.
1 2 3 4 5 6 7 8 9 10 11 | function Car(){ var vehicle = new Vehicle(); var car = objectPlus(vehicle, { objName: 'Car', type: 'unknown', getObjName: function(){ return this.uber.getObjName() + ', ' + this.objName; } }); return car; } |
Here are the details for the objectPlus method. You should grab this code snippet and put it in your utils library, as you will use this code over and over again in object-orientated programming.
1 2 3 4 5 6 7 8 9 10 11 12 | function objectPlus(obj, stuff) { var n; function F(){} F.prototype = obj; n = new F(); n.uber = obj; for (var i in stuff){ n[i] = stuff[i]; } return n; } |
The next step is to build an object that represents different types of cars, like sports cars, hatch backs, etc. Keeping it simple, we are only going to build a sports car object, which clones car using objectPlus, sets the type property to sports car (overwriting the default defined in vehicle), and adds a new getInfo function, that will build a string from all the properties inherited from all the objects cloned. In a moment you will see exactly how this works, but suffice it to say that the color and make properties exist only in the base vehicle object we started with, but when we reference those properties in the sports car object, JavaScript will look up the prototype chain of objects that were cloned until it finds them.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | function SportsCar (){ var car = new Car(); var sportsCar = objectPlus(car, { objName: 'SportsCar', type: "Sports Car", premiumPaint: 'unknown', getInfo: function(){ return this.color + " " + this.make + " " + this.name + " " + this.type + " - " + this.mpg + "mpg" + " - " + this.premiumPaint; } }); return sportsCar; } |
Okay, now is our chance to test this out. Are we having fun yet? We are going to create a new sports car, then clone it using objectPlus to make a Corvette. When we call the getInfo function, we can see that all properties from the cloned objects in the prototype chain are accessible to us. Some of the properties and functions reside in the base vehicle object, some in the car object, some in the sports car object; JavaScript looks up the prototype chain until it finds them or fails. We can even call the getName function which will display for us the prototype chain so we can see what we did. Cool, huh?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | // Prototypal inheritance (Works) var sportsCar = new SportsCar(); var myCorvette = objectPlus(sportsCar, { name: "Corvette", make: "Chevy", color: "White", premiumPaint: 'Pearl White', mpg: 10 }); application.output(myCorvette.getInfo()); // White Chevy Corvette Sports Car - 10mpg - Pearl White application.output("Prototype chain: "+ myCorvette.getObjName()); // Prototype chain: Vehicle, Car, SportsCar, Corvette |
Objects are awesome! Once you understand how to use them, your code will become more modular, maintainable, extendable, elegant, and the envy of Servoy Developers everywhere. Maybe its time to ask for a raise?