Are multiple "constructors" allowed in JavaScript?

A

andrewfsears

I have a question: I was wondering if it is possible to simulate the
multiple constructors, like in Java (yes, I know that the languages are
completely different)?

Let's say that I have a class called "Point" which would have two
values "x" and "y".

Now, let's say if it were the Java version, I would want two
constructors: one that accept two numbers, the other accepts a string:

public class Point {
private int x;
private int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public Point(String coord) {
this.x = coord.charAt(0);
this.y = coord.charAt(1);
}
...
}


In JavaScript, so far I have

Point = function() {
var x;
var y;
...
}

Is it possible to have two declarations for the Point.prototype.init?
Is it even possible to have multiple constructors in JavaScript?

Thanks for the help, Andy
 
V

VK

I have a question: I was wondering if it is possible to simulate the
multiple constructors, like in Java (yes, I know that the languages are
completely different)?

Let's say that I have a class called "Point" which would have two
values "x" and "y".

Now, let's say if it were the Java version, I would want two
constructors: one that accept two numbers, the other accepts a string:

public class Point {
private int x;
private int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public Point(String coord) {
this.x = coord.charAt(0);
this.y = coord.charAt(1);
}
...
}


In JavaScript, so far I have

Point = function() {
var x;
var y;
...
}

Is it possible to have two declarations for the Point.prototype.init?
Is it even possible to have multiple constructors in JavaScript?

What you want shall be called "polymorphic function-constructor". As
you properly noticed, a polymorphic constructor (in any language) is in
fact two or more constructors "hidden" under one common interface
(explicit in JavaScript or implicit in Java). The rest gets simple:

<script type="text/javascript">
function Point() {
switch (typeof arguments[0]) {
case 'number' : Point.$int.apply(this, arguments); break;
case 'string' : Point.$str.apply(this, arguments); break;
case 'object' : Point.$obj.apply(this, arguments); break;
default : /*NOP*/
}
}

Point.$int = function(x, y) {
this.x = x;
this.y = y;
};

Point.$str = function(coord) {
this.x = parseInt(coord.charAt(0), 10);
this.y = parseInt(coord.charAt(0), 10);
}

Point.$obj = function(obj) {
this.x = obj.x;
this.y = obj.y;
}

var p1 = new Point(2,2);
var p2 = new Point('22');
var p3 = new Point({x:2, y:2});

alert(p1.x); alert(p1 instanceof Point);
alert(p2.x); alert(p2 instanceof Point);
alert(p3.x); alert(p3 instanceof Point);
</script>

Needless to say that the arguments check for validity has to be added;
also "coord.charAt" is good only for a quick'n'durty demo (or if
guaranteed 0-9 coords range).
 
A

andrewfsears

VK,
Thank you very much for your response. Very helpful.
also "coord.charAt" is good only for a quick'n'durty demo (or if
guaranteed 0-9 coords range).

And yes, the string-construct was just a quick-and-dirty sample to get
the point across on this post; it will be much fuller...
 
R

Richard Cornford

That may as well be:-

function Point() {

- as that function declaration will have precisely the same result as
the assignment of a function expression to an undeclared Identifier, but
the function object will be created sooner (during variable
instantiation for the global execution context, and it will not be
possible to delete the - Point - property of the global object (though
it is extremely unlikely that anyone would attempt that anyway).

I would also be expecting to see declared formal parameters. Javascript
doesn't care about the type of arguments passed to any of its functions,
or whether all or any arguments are passed at all (defaulting unused
parameters to undefined id they are not used).
var x;
var y;
...
}

Is it possible to have two declarations for the
Point.prototype.init? Is it even possible to have
multiple constructors in JavaScript?

What you want shall be called "polymorphic function-constructor".
As you properly noticed, a polymorphic constructor (in any
language) is in fact two or more constructors "hidden" under
one common interface (explicit in JavaScript or implicit in
Java). The rest gets simple:

<script type="text/javascript">
function Point() {
switch (typeof arguments[0]) {
case 'number' : Point.$int.apply(this, arguments); break;
case 'string' : Point.$str.apply(this, arguments); break;
case 'object' : Point.$obj.apply(this, arguments); break;
default : /*NOP*/
}
}

Point.$int = function(x, y) {
this.x = x;
this.y = y;
};

Point.$str = function(coord) {
this.x = parseInt(coord.charAt(0), 10);
this.y = parseInt(coord.charAt(0), 10);
}

Point.$obj = function(obj) {
this.x = obj.x;
this.y = obj.y;
}

Yet another pig's ear of an implementation from the VK school of never
understanding javascript well enough to do what is natural in the
language. In javascript you would naturally write such an object as:-

function Point(a, b){
switch(typeof a){
case 'number':
this.set(a, b);
break;
case 'string':
this.setWithString(a);
break;
case 'object':
this.setWithPoint(a);
break;
default:
break;
}
}
Point.prototype.x = NaN; //or some other default value like zero.
Point.prototype.y = NaN;

Point.prototype.set = function(x, y){
this.x = x;
this.y = y;
};

Point.prototype.setWithString = function(coord){
this.x = Number(coord.charAt(0));
this.y = Number(coord.charAt(1));
};

Point.prototype.setWithPoint = function(point){
this.x = point.x;
this.y = point.y;
};

- and so avoid having ragged and useless methods (could never be used as
methods of the constructor function object) hanging off the constructor
function, avoid the unnecessary dependency on -
Function.prototype.apply -(which designs out compatibility with JScript
versions prior to 5.6 at a stroke, for no real reason), avoids the
overheads in using - Function.prototype.apply -, and provides the -
Point - object instances with a group of 'setter' methods that may be
useful in modifying/updating/transforming those objects.

So that is: smaller, faster, clearer, cleaner, more widely compatible
and resulting in an object with more useful features.
var p1 = new Point(2,2);
var p2 = new Point('22');
var p3 = new Point({x:2, y:2});

alert(p1.x); alert(p1 instanceof Point);
alert(p2.x); alert(p2 instanceof Point);
alert(p3.x); alert(p3 instanceof Point);
</script>

Needless to say that the arguments check for validity has to
be added; also "coord.charAt" is good only for a
quick'n'durty demo (or if guaranteed 0-9 coords range).

It might still have been an idea not to use index zero with - charAt -
to set both - x - and - y - coordinates.

Richard.
 
J

John G Harris

I have a question: I was wondering if it is possible to simulate the
multiple constructors, like in Java (yes, I know that the languages are
completely different)?
<snip>

There's nothing wrong with having several constructors with different
names for the same 'class' of objects, provided their prototype
properties are given the same value and new objects are given the right
properties. The advantage is that each constructor is cleaner. You don't
have to test the number and type of the parameters (that's not very OO,
is it).

There's nothing new or strange about this. It's the way Borland's Turbo
Pascal did it.

John
 
V

VK

Richard said:
function Point(a, b){
switch(typeof a){
case 'number':
this.set(a, b);
break;
case 'string':
this.setWithString(a);
break;
case 'object':
this.setWithPoint(a);
break;
default:
break;
}
}
Point.prototype.x = NaN; //or some other default value like zero.
Point.prototype.y = NaN;

Point.prototype.set = function(x, y){
this.x = x;
this.y = y;
};

Point.prototype.setWithString = function(coord){
this.x = Number(coord.charAt(0));
this.y = Number(coord.charAt(1));
};

Point.prototype.setWithPoint = function(point){
this.x = point.x;
this.y = point.y;
};

That is another viable approach. What I don't like in it (doesn't mean
others have to share my feelings) - is that "obfuscates" the
inheritance chain.
Polymorphism is a horizontal process: from the entry point it goes
left, right or straight depending on arguments. Inheritance is a
vertical process (from parent to parent). This way I don't see useful
to enforce "vertical onto horizontal". As the result each Point
instance is getting a full set of sub-constructors from its constructor
with future possible fanny actions like:
var p = new Point(2, 2);
var foo = new p.set(22, 22);
// foo has nothing to do with Point if anyone wonders.

So it's a bit like gluing on each newly born chicken the leftovers of
its egg - IMHO.

Full disclosure: that's a historical moment when I do agree with John G
Harris :) I think that polymorphism in the programming is more of an
esthetical mannerism (see my cool vs. lame notes) rather than something
technically needed.
That is not to target to OP: please take it as an overall consideration.
 
R

Richard Cornford

VK said:
That is another viable approach.

So that garbage you posted is justified once again by your claim that it
"works", regardless of drunkenly it staggers while doing so?
What I don't like in it (doesn't mean
others have to share my feelings)

It would be amazing (and very unfortunate for them) if anyone else did.
- is that "obfuscates" the inheritance chain.

And how do you propose it is doing that? We understand that you are only
just becoming aware of prototypes in javascript and their significance
in inheritance, but that just means that what you may perceive as
obscure reflects only your very limited comprehension of the language.
Polymorphism is a horizontal process: from the entry point
it goes left, right or straight depending on arguments.
Inheritance is a vertical process (from parent to parent).
This way I don't see useful to enforce "vertical onto
horizontal".

What you don't see is a matter of no interest, particularly as it
results in your writing irrelevancies like that.

I have written one 'class' definition with a constructor that can take a
number of types of argument. That is all, and it is precisely what you
did, except your version was not informed by an understanding of
javascript.
As the result each Point instance is getting a full
set of sub-constructors from its constructor

Rubbish. Each - Point - instance is being defined with a set of 'setter'
methods. Those methods happen to be being employed by its contractor,
but there is no reason for not doing that.

"setter" (and "getter") methods are familiar concepts in OO programming,
and the OP will certainly have no trouble relating them directly to what
he has previously seen in Java. While your ragged collection of methods
of the constructor that can only be sensibly used with the -
apply/call - methods only pile needless complexity on the subject. They
are more a source of 'obfuscation' than anything I have written.
with future possible fanny actions like:
var p = new Point(2, 2);
var foo = new p.set(22, 22);

You blithering idiot. I know that you program without any understanding
of what the code you write is actually doing, and so might do something
as stupid as using the - new - operator on a function that is referred
to by the name "set" just because you can (and it will "work", by some
very broad definition of the word), but do you really think any real
programmers (and particularly experienced OO programmers) are going to
do anything so obviously stupid?
// foo has nothing to do with Point if anyone wonders.

And - p.set - is so obviously not intended to be used as a constructor
that nobody would expect it to.
So it's a bit like gluing on each newly born chicken the
leftovers of its egg - IMHO.

It is opinions like that that justify the observation that your opinions
are universally worthless.
Full disclosure: that's a historical moment when I do agree
with John G Harris :)

You may think you do, but it is more likely that you did not understand
him.
I think that polymorphism in the programming is more of
an esthetical mannerism (see my cool vs. lame notes) rather
than something technically needed. That is not to target
to OP: please take it as an overall consideration.

That loose aggregation of words does not say one way or the other.

Richard.
 
V

VK

What I don't like in it (doesn't mean
And how do you propose it is doing that?

In the way it supposes - IMHO - to be: if one really made her mind to
have a polymorphic constructor then she also should provide polymorphic
setter to the instances.

It doesn't prohibit using the native prototype mechanics: it even may
add some more elegance to the code (but no more effectiveness):

<html>
<head>
<title>Demo</title>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">
<script type="text/javascript">

function Point() {
this.set.apply(this, arguments);
}

Point.prototype.set = function() {
/* Arguments check is ommited
* in this sample for simplicity
*/
if (this instanceof Point) {
switch (typeof arguments[0]) {
case 'number':
this.x = arguments[0];
this.y = arguments[1];
break;
case 'object':
this.x = arguments[0]['x'];
this.y = arguments[0]['y'];
break;
default:
throw new Error('Illegal arguments : Point.set()');
}
}
else {
throw new Error('Illegal method call : Point.set()');
}
}

var p = new Point(2, 2);
alert(p.y);

p.set(3, 3);
alert(p.y);

p.set({x:4, y:4});
alert(p.y);

try {
p.set('foo');
}
catch(e) {
alert(e.message);
}

try {
var pp = new p.set(1, 1);
}
catch(e) {
alert(e.message);
}
</script>
</head>
<body>
</body>
We understand that you are only
just becoming aware of prototypes in javascript

Funny enough it is exactly my impression about you ;-)

<http://groups.google.com/group/comp.lang.javascript/msg/c7abb8fdbb341f56>

<snip>
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top