No that is not an example of polymorphism as each instance is the same object. Just giving them different names does not change the type.
Update. I overlooked the assignment of a new function to the object named triangle
. That also does not constitute an example of polymorphism.
Super Polymorphism *
(*) (not a real term in CS as far as I know)
There are a wide variety of ways to define objects and functions for the objects. It is not the object type that determines the behaviour provided by shared functions (more apt than calling them polymorphic)
The requirement be only that they provide the correct set of properties and behaviours for shared functions to operate on. In a sense the ultimate form of polymorphism, truly independent of type and thoroughly unsafe as is any super power if you don't learn to use it with care.
Examples of polymorphic like JS.
Personally I don't like to use the term polymorphic in JS as JS does not really define an interface, however as shown below you could consider polymorphic like behaviours
function position(x,y){
this.x = y;
this.y = y;
// The next function if considered as an interface to the object
// can be thought of as polymorphic as it is independent of the
// object type.
this.translate = function(x,y){
this.x += x;
this.y += y;
}
// A more generic type of polymorphic interface
// will work for any object. If it has a w,h property it has
// 4 sides if not it has 0
this.noSides = function(){
// deductive property looks at objects properties to
// workout the number of sides.
if(this.w && this.h){ return 4 }
return 0; // Circle has no sides
}
}
function Box(x,y,w,h){
this.w = w;
this.h = h;
position.call(this, x, y);
this.scale = function(scale){
this.w *= scale;
this.h *= scale;
}
}
function Circle(x,y,r) {
this.r = r;
position.call(this, x, y);
this.scale = function(scale){
this.r *= scale;
}
}
// though not a polymorphic object interface it is a function
// that only requires properties not an object type so is
// a form of a polymorphic interface
function scalePos(obj, scale){
obj.x *= scale;
obj.y *= scale;
obj.scale(scale); // call object specific scale
}
var box = new Box(10,10,100,100);
var circle = new Circle(10,10,100);
box.translate(10,10);
circle.translate(10,10);
scalePos(box,10);
scalePos(circle,10);
Inferred object type
Or the ad-hoc construction approch can be called polymorphic using a factory function (or frankensteiner as I like to call from time to time)
Objects are created from parts Each part on its own is barely a usable object, only together do they become a usable object (alive). The resulting objects are in a sense typeless objects that share polymorphic functionality.
const box = {
w : 0,
h : 0,
};
const circle = {
r : 0,
};
const position = {
x : 0,
y : 0,
};
// polymorphic functions
const moveable = {
translate(x, y) {
this.x += x;
this.y += y;
}
};
const growable = {
scale(scale) {
this.x += x;
this.y += y;
if (this.r) { this.r *= scale }
if (this.w) { this.w *= scale }
if (this.h) { this.h *= scale }
},
};
const definable = {
get sides() {
return this.r !== undefined ? 0 : 4;
},
};
// define common set of behaviours
const polySet = [moveable, growable, definable];
// factory function called frankensteiner because you have to
// include the object's state (zap the life into the object) as the
// last part of the construction.
function frankensteiner(...parts) {
return Object.assign({}, ...parts);
}
// types is inferred by property and functionality and is completely abstract
var point = frankensteiner(position, moveable ,{x: 10, y: 10});
var box1 = frankensteiner(box, position, ...polySet,{x: 10, y: 10, w: 100, h: 100});
var circle1 = frankensteiner(circle, position, ...polySet,{x:10,y:10,w:100,h:100});
var circleBox = frankensteiner(circle, box, position, ...polySet, {x: 10, y: 10, w: 100, h: 100, r: 100});
//point has not scale
box1.scale(2);
circle1.scale(2);
circleBox.scale(2);
point.translate(2,2);
box1.translate(2,2);
circle1.translate(2,2);
circleBox.translate(2,2);
You can make the object factory smart and add properties and functions depending on the parts its made of.
Or you can use the class syntax or direct to prototype and have a stricter form of inheritance via prototypes. Though closer to real polymorphism it still is not class safe.
No class safety
Without the strict classing of languages like C++ and Java there is no real object type. At any stage I can change an object
box.name = "Bob";
And in the strict class definition it is no longer a true instanceOf Box
, it has been mutated. The mutation can make polymorphic like interfaces unsafe
box.x = "center";
It has meaning but the functions that rely on x
being the correct type (Number
) will fail. In JS the mutated box is still an instanceof Box
and to be safe you would have to vet each property in turn. Not at all a practical form of polymorphism.