Constructors Which Create Constructors (JavaScript) - javascript

In a simulation I'm making, I'll have an Element class, which I'll call with params about the properties of that Element (melting and boiling temperatures, rules for reactions with other Elements, color, density, etc.) to create the basic types of Elements (water, oxygen, carbon, etc.). From these, I simply would like to create new "Atoms" from the water, oxygen, and carbon templates I would have. I'm wondering if there's a way to use a constructor (Element) to create a new constructor (like Water)? For example, I would like to be able to do something like this.
var Element = function(/* params */) {
// common element properties and basic functions
}
var Water = new Element(); // create the new element
var WaterAtom = new Water(); // create the atom (an instance of the element)
// draw the atom, manipulate it, react with other atoms, etc.
I'm basically asking, can a constructor create another constructor? I would like it this way so I don't have to create tons and tons of .prototype code that extends the basic Element class.

I think what you are looking for is
function Element(…) {
// init properties that all elements share
}
Element.prototype.… = function(…) { … }; // add all methods of elements
Element.makeType = function(rules) {
function ElementType(…) {
Element.call(this, …);
}
ElementType.prototype = Object.create(Element.prototype);
ElementType.prototype.constructor = ElementType;
ElementType.prototype.rules = rules;
return ElementType;
};
so that you can use it like
var Water = Element.makeType(function(…) {
// do whatever makes water special
});
var drop = new Water(…);

You could just write a utility function for generating subclasses of Element:
function Element() {}
function subElement() {
function SubElement() {}
SubElement.prototype = Object.create(Element.prototype);
return SubElement;
}
var Water = subElement();
var waterAtom = new Water();

Related

JavaScript efficient solution for multi-inheritance

Why this question is not a duplicate
This answer javascript inheritance from multiple objects does not solve my problem (although it has been marked as a duplicate of my previous question), because it is not scalable as it violates the DRY principle.
For this to work, one would have to manually reference each method like this :
Foo2.prototype.a = function() { /*code...*/};
Foo2.prototype.b = function() { /*code...*/};
Foo2.prototype.c = function() { /*code...*/};
Foo2.prototype.d = function() { /*code...*/};
//and so on and so on...
And what if I have dozens of classes containing dozens of methods ? Should I really manually copy-paste the same reference for each and every class over and over again in my source code ? While this solution would work for a very low number of classes, it is just not usable in a large-scale application using dozens or hundreds of classes.
The problem I'm trying to solve
I'm trying to instantiate objects which must inherit all the properties and methods of Animal and Flying_object using new keyword.
var objA = new Fish(),
objB = new Bird(),
objC = new UFO();
Tricky part is Animal and Flying_object can NOT have a parent-child relationship.
I know JavaScript doesn't implement native methods for multi-inheritance, so I'm posting this question to get some help finding a custom, scalable solution to this problem.
Code example and expected behavior
var Living_being = function() { this.className = 'Living_being'; };
var Animal = function() {
this.className = 'Animal';
this.vector = {x: 0, y: 0};
}
Animal.prototype = new Living_being();
Animal.prototype.getClassName = function() { console.log('Instance of... '+ this.className); };
Animal.prototype.get_vector = function() { console.log(this.vector); }
var Flying_object = function() {
this.className = 'Flying_object';
this.value = 'some value';
}
Flying_object.prototype.getClassName = function() { console.log('Instance of... '+ this.className); };
Flying_object.prototype.get_val = function() { console.log(this.value); }
// So far so good...
var UFO = function() {};
UFO.protoype = new Flying_object(); //classical inheritance
var Fish = function() {};
Fish.protoype = new Animal(); //classical inheritance
// Now the tricky part: how to make Bird share all of the methods and properties of Animal and Flying_object ?
var Bird = function() {};
Bird.prototype = new ....(); //pseudocode where .... is a class containing all the properties of Animal and Flying_object
var instance = new Bird();
//expected result:
instance.getClassName();//--> Instance of...
instance.get_vector(); //--> {x: 0, y: 0}
instance.get_val(); //--> 'some value'
This is where I'm stuck. How can I make Bird inherit from BOTH Animal and Flying_object ?
Any insight would be greatly apprenciated.
Here is a working solution I came up with at some point and gave up because I though there might be a better solution.
#Mörre: I'm not sure this is what you advised me to do in the comments: is this what you called object composition ? Or am I going all wrong here ?
Demo: https://jsfiddle.net/Lau1989/4ba8yrc8/1/
function mix(classA, classB) {
var instanceA = new classA(),
instanceB = new classB();
for (var prop in instanceA) {
instanceB[prop] = instanceA[prop];
}
return instanceB;
}
var Bird = function() { this.className = 'Bird'; };
Bird.prototype = mix(Animal, Flying_object);
var instance = new Bird();
If you need inherit from few classes you can extend prototype Bird from Animal and Ufo using jquery function $.extend({});.
Example $.extend(Bird.prototype,Animal.prototype,UFO.prototype) or you can create custom extend function.If names properties or functions has same names , they will be rewrite.
I got this from documentation: Using Object.assign() extend only enumerable properties.The Object.assign() method only copies enumerable and own properties from a source object to a target object. It uses [[Get]] on the source and [[Set]] on the target, so it will invoke getters and setters. Therefore it assigns properties versus just copying or defining new properties. This may make it unsuitable for merging new properties into a prototype if the merge sources contain getters. For copying property definitions, including their enumerability, into prototypes Object.getOwnPropertyDescriptor() and Object.defineProperty() should be used instead.
JavaScript does not support the concept of multiple inheritance. It also does not implement syntax for mixin and/or trait based composition. But unlike the former, the latter can be achieved by e.g. function and delegation based mixin patterns.
Thus, one first needs to figure out which parts of a composable object system should build the 'is a' relationship and which parts are behavior ('can do' / 'has a') that might get reused by/at different parts/levels of the object system.
The OP already has done this work. The example code that will be provided below is just going to introduce different function based mixin patterns via providing implementations of some behaviors like withLivingBeingBasics and withFlyingAbility ... with the first mixin covering the OP's Living_being class and the second one covering Flying_object.
For better code reuse there are 2 additional mixins, withExposeClassName and withExposeVector that, for the reason of demonstration, compose into the withExposeClassNameAndVector mixin compound.
From this possible base setup, that follows the OP's example, one could continue with shaping the classes.
With the Animal class one is free of choosing where mixin composition shall take place. Following the provided original example, composition at class/prototype level is the better option instead of applying the behavior at construction/instantiation time from within the constructor.
After applying withExposeClassNameAndVector and withLivingBeingBasics to Animal.prototype, any animal instance via prototypal delegation is capable of being invoked at getClassName and getVector as well as at metabolize and reproduce. Thus, at this point, both mixin composition (explicit delegation via call to prototype) and inheritance (automatically running delegation via prototype chain) take place.
The Fish class is implemented easily. As with the OP's example one just follows a simplified inheritance pattern via Fish.prototype = new Animal;. In addition, as already featured with the Animal base class, a class' name gets assigned to its prototype object.
Bird repeats the base patterns of Fish with the exception of featuring its own vector property that now is three dimensional instead of the otherwise prototypal two dimensional one. And since a common bird is supposed to somehow feature flying behavior Bird.prototype has to acquire it from withFlyingAbility.
Following still the OP's example, Ufo also needs to have flying ability. And like a bird, an ufo too has to feature an own three dimensional vector property. Thus the property gets assigned at construction/instantiation time and all the needed behavior gets applied from withExposeClassNameAndVector and from withFlyingAbility to Ufo.prototype.
The provided approach intends to prove that ... the most atomar mixin implements exactly one behavior, ... mixins are not necessarily supposed to introduce state but a behavior might operate upon state, ... mixins can be composed from other mixins, ... they always get applied at object level, either to already existing objects or to the prototype object itself or at composition time from within a constructor function ...
var withLivingBeingBasics = (function () { // function based mixin
function metabolize() { // implement beahvior once.
console.log('every living being features some kind of metabolism.');
}
function reproduce() { // implement beahvior once.
console.log('every living being features some kind of reproduction.');
}
return function() {
this.metabolize = metabolize; // assign shared code.
this.reproduce = reproduce; //
}
}());
var withFlyingAbility = (function () {
function liftOffAerodynamically() {
this.vector.z = 5;
console.log('flying needs some kind of aerodynamic lift.');
}
function monitorAltitudeDifference() {
console.log('monitoring altitude difference : ', this.vector.z);
}
return function() {
this.liftOffAerodynamically = liftOffAerodynamically;
this.monitorAltitudeDifference = monitorAltitudeDifference;
}
}());
var withExposeVector = (function () {
function getVector() {
console.log('vector : ', this.vector);
}
return function() {
this.getVector = getVector;
}
}());
var withExposeClassName = (function () {
function getClassName() {
console.log('Instance of... ', this.className);
}
return function() {
this.getClassName = getClassName;
}
}());
var withExposeClassNameAndVector = function () { // mixin compound.
withExposeClassName.call(this);
withExposeVector.call(this);
}
function Animal() {
//withLivingBeingBasics.call(this); // mixing in for the given example is …
//this.className = 'Animal'; // … better at **class**/prototype level.
this.vector = {x: 0, y: 0};
}
// the many ways of augmenting the `prototype` ...
Object.assign(Animal.prototype, { className: 'Animal' });
//withExposeClassName.call(Animal.prototype);
//withExposeVector.call(Animal.prototype);
withExposeClassNameAndVector.call(Animal.prototype);
withLivingBeingBasics.call(Animal.prototype);
function Fish() {}
Fish.prototype = new Animal;
Object.assign(Fish.prototype, { className: 'Fish' });
function Bird() {
this.vector = {x: 0, y: 0, z: 0};
}
Bird.prototype = new Animal;
Object.assign(Bird.prototype, { className: 'Bird' });
withFlyingAbility.call(Bird.prototype);
function Ufo() {
this.vector = {x: 0, y: 0, z: 0};
}
Object.assign(Ufo.prototype, { className: 'Ufo' });
//withExposeClassName.call(Ufo.prototype);
//withExposeVector.call(Ufo.prototype);
withExposeClassNameAndVector.call(Ufo.prototype);
withFlyingAbility.call(Ufo.prototype);
var fish = new Fish;
var bird = new Bird;
var ufo = new Ufo;
console.log('(fish instanceof Animal) ? ', (fish instanceof Animal));
console.log('(fish instanceof Fish) ? ', (fish instanceof Fish));
fish.getClassName();
fish.metabolize();
fish.reproduce();
fish.getVector();
console.log('(bird instanceof Animal) ? ', (bird instanceof Animal));
console.log('(bird instanceof Bird) ? ', (bird instanceof Bird));
bird.getClassName();
bird.metabolize();
bird.reproduce();
bird.getVector();
bird.monitorAltitudeDifference();
bird.liftOffAerodynamically();
bird.monitorAltitudeDifference();
console.log('(ufo instanceof Ufo) ? ', (ufo instanceof Ufo));
ufo.getClassName();
ufo.getVector();
ufo.monitorAltitudeDifference();
ufo.liftOffAerodynamically();
ufo.monitorAltitudeDifference();
.as-console-wrapper { max-height: 100%!important; top: 0; }
For further reading on SO one might give the following related questions and solutions a chance ...
What are the practical differences between Mixins and Inheritance in Javascript?
Mixins for ES6 classes, transpiled with babel
Traits in javascript
Accessors Composition in ES6 Classes

How to create new instance of parent class in javascript

I have a class that inherits from another. Within the base class, I'm wondering if it is possible to create and return a new instance of the calling parent class.
Here's an example:
Base:
var util = require('util');
var ThingBase = function(options) {
}
ThingBase.prototype.mapper = function(data) {
// do a bunch of stuff with data and then
// return new instance of parent class
};
Parent:
var FooThing = function(options) {
ThingBase.call(this, options);
};
util.inherits(FooThing, ThingBase);
FooThing.someMethod = function() {
var data = 'some data';
var newFooThing = this.mapper(data); // should return new FooThing instance
};
The reason why I wouldn't just create a new instance from someMethod is that I want mapper to do a bunch of stuff to the data before it returns an instance. The stuff it will need to do is the same for all classes that inherit from Base. I don't want to clutter up my classes with boilerplate to create a new instance of itself.
Is this possible? How might I go about achieving something like this?
Assuming that FooThing.prototype.constructor == FooThing, you could use
ThingBase.prototype.mapper = function(data) {
return new this.constructor(crunch(data));
};
All other solutions would "clutter up [your] classes with boilerplate [code]", yes, however they don't rely on a correctly set constructor property.

Is init a special reserved keyword for Javascript Object Literals?

I ran across the following Javascript code.
var Zoo = {
animals: [],
init: function (animal_list) {
for (i = 0; i < animal_list.length; i++) {
this.animals.push(animal_list[i]);
}
}
It looks like the init key maps to an executable function. That function takes in an animal list each item in the list into an animal array.
If I were in my native tongue Ruby, I would do something like this:
class Zoo
def initialize animal_list
#animals = animal_list #animal_list is an array
end
end
So is init the javascript equivalent of an initialize function? In ruby, I can call
my_ruby_zoo = Zoo.new ["lions", "tigers", "bears"]
In javascript, does the init function map to
var my_javascript_zoo = Zoo.new( ["lions", "tigers", "bears"]);
Is init a special reserved keyword for Javascript Object Literals?
No, not at all. There is no pre-named function for initialization in JavaScript. Typically, if you have need of a "class" of objects in JavaScript, you use a constructor function with the new keyword:
function Person(first, last) {
this.first = first;
this.last = last;
}
// Usage:
var chuck = new Person("Charles", "Foreman");
You might then add functions that all instances created via new Person can use, by adding them as properties to the prototype that gets assigned to objects created via new Person (that prototype is taken from the Person.prototype property):
Person.prototype.getFullName = function() {
return this.first + " " + this.last;
};
Because this is a bit long-winded and handling inheritance hierarchies is more effort than it is in other languages (something that's being fixed in ES6), there are a lot of libraries out there that provide helper functions to hook things up for you. (Mine is called Lineage, there's also Resig's Really Simple Inheritance, PrototypeJS's Class, etc.) Some of these helper scripts may give certain function names special meaning. For instance, in both Lineage and PrototypeJS's Class, a function called initialize is special. (I've seen some where ctor was special.)
But not within JavaScript itself.
Your Zoo might look like this:
function Zoo(animal_list) {
this.animals = animal_list.slice(0); // Copy the array
}
If you want to add functions available on all Zoo instances, typically you'd add them to the prototype assigned by new Zoo:
Zoo.prototype.showAll = function() {
this.animals.forEach(function(animal) {
console.log(animal);
});
};
// Usage:
var z = new Zoo(['Tortoise', 'Emu', 'Lion']);
z.showAll();
If you want to make your Zoo class a constructor it should be a function instead of an object literal:
var Zoo = function(animal_list) {
this.animals = [];
for (i = 0; i < animal_list.length; i++) {
this.animals.push(animal_list[i]);
}
}
var myZoo = new Zoo(["lions", "tigers", "bears"]);

How to extend a class in JavaScript

I'm working on a chess game built in JavaScript. I'm taking an object-oriented approach to it and am having some difficulty working with JavaScript's inheritance. I want there to be a "Piece" abstract class that holds some fields and basic getters/setters such as is this piece black or white. I then want to have classes for each type of piece that I can instantiate like so:
var pieceOne = new Pawn();
The Pawn() should have all the fields and methods of Piece but have its own method for movement, and additional fields (such as whether or not it has moved yet, as this doesn't matter for most pieces). Here's my current Piece class:
//This object specifies basic information about pieces.
"use strict";
function Piece(color, type, captured, hasMoved) {
this.color = color;
this.type = type;
this.captured = captured;
this.hasMoved = hasMoved;
this.image = color + "_" + type + ".svg";
}
Piece.prototype.getImage = function getImage(){
return this.image;
}
Piece.prototype.isCaptured = function isCaptured(){
return this.captured;
};
I know if I am going to make a subclass for every kind of piece that I'd probably eliminate the "type" field, but how could I make a Pawn subclass? Something like this?
function Pawn() = new Piece(color, captured, hasMoved);
Pawn.prototype.getLegalMoves = function getLegalMoves(){
//return legal moves
}
var pieceOne = new Pawn("black", false, false);
Extending a class can be done in different ways. The simplest method to extend an class is to use Object.create method. This is common method which is used to achieve abstraction (Link to my blog). Let's give an example of the Object.create method as follows.
var Logger = { log : function(log){} }
var ConsoleLogger = function() {};
ConsoleLogger.prototype = Object.create(Logger);
If you are willing to take an object oriented approach on JS I would recommend you to follow the power constructor pattern.
Basically you have a function that creates objects for you and take advantage of the closures to hide the internal properties (fields or methods).
function myObject(){
var that={};
var myPrivateField;
var myPrivateFunction=function(){
}
that.myPublicMethod=function(){
}
return that;
}
Then you can just call the method myObject() and you will get a new object of this type.
You can extend this example to use inheritance by just calling the power constructor of another object and then use object augmentation. Take a look at the example of parasatic inheritance of Douglas Crockford.
You can call Piece's constructor from Pawn and have that constructor operate on the Pawn instance:
function Pawn(/* args... */) {
Piece.call(this, color, type, captured, hasMoved);
/* Pawn-specific constructor code... */
}
I believe it's just a matter of setting the prototype of the specific piece constructors to an instance of Piece. For example:
Pawn.prototype = new Piece("", false, false);
However, this will not call the Piece (super) constructor every time you instantiate a new Pawn, so you'll have to manually assign color, type, etc. from the Pawn constructor:
-- EDIT --
You might prefer this instead: Javascript inheritance: call super-constructor or use prototype chain?
Take a look at this: https://github.com/haroldiedema/joii
var BaseClass = function()
{
this.some_var = "foobar";
/**
* #return string
*/
this.someMethod = function() {
return this.some_var;
}
};
var MyClass = new Class({ extends: BaseClass }, function()
{
/**
* #param string value
*/
this.__construct = function(value)
{
this.some_var = value;
}
})
Usage:
var obj = new MyClass("Hello World!");
console.log( obj.someMethod() ); // Hello World!

JavaScript – Prototype Inheritance without overwriting the base class [duplicate]

This question already has an answer here:
Why can't I call a prototyped method in Javascript?
(1 answer)
Closed 10 years ago.
I’m building a card game in JavaScript in order to increase my web programming chops, and I’m having an issue with JavaScript Prototype inheritance. My design has a base Card class that contains all of the function and data any card will ever need. The design itself is relatively flexible, so just by changing the data stored about 25% of cards can use the base class. What I need to do is create new classes that inherits everything from Card – including the data – but overrides a small subset of the available functions without touching the base class functions.
I’ve been attempting to use prototype inheritance to accomplish this, but this changes the base class, which not only screws up any cards using the Card class, but also every other function that inherits from the base class.
What I need is a design pattern that allows me to override a function ONLY for the classes inheriting from Card. Is this possible in JavaScript?
Edit...
Sorry, here's an example, probally should have added this in the first place.
Starting with the Base Card class.
function Card(){
this.cardID = 0;
this.name = '';
this.imageID = 0;
this.imageURL = '';
this.imageAlt = '';
etc....
}
Card.prototype.init = function( inID
, inName
, inImageID
, inImageURL
, inImageAlt
, inImageHorizontal
etc...
){
this.cardID = inID;
this.name = inName;
this.imageID = inImageID;
this.imageURL = inImageURL;
this.imageAlt = inImageAlt;
}
Card.prototype.whenPlayed = function(){
return false;
}
Now my Child Class:
ChildCard.prototype = new Card();
ChildCard.constructor = ChildCard;
function ChildCard(){};
ChildCard.prototype.whenPlayed = function(){
alert("You Win!");
return true;
}
As it stands now if I were to create a Card object and call its whenPlayed I'd get the behavior from ChildCard not Card.
The issue I'm really facing here is the card class has approaching 3 donzen methods, and I don't want to have to define each one in each child class.
A quite simple and straightforward pattern:
function Parent(arg) {
this.someProperty = arg;
// initialize all instance properties in the constructor
}
// The prototype should only contain methods and primitive values.
Parent.prototype.someMethod = function() {
// ...
};
Parent.prototype.someOtherMethod = function() {
// ...
};
function Child(arg1, arg2) {
// call parent constructor -- like super() in other languages
Parent.call(this, arg1);
// initialize all instance properties in the constructor
}
// Hook up Base.prototype into the prototype chain
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child; // not necessary but can be useful
Child.prototype.someMethod = function() {
// override method and call parent method
Base.prototype.someMethod.call(this);
// ...
};
It relies on Object.create [MDN]. It creates a new object which inherits from the passed in object. So you get one level of indirection between Child.prototype and Parent.prototype, i.e. changes to Child.prototype don't influence `Parent.prototype.

Categories