Lasse Reichstein Nielsen <lr*@hotpop.com> wrote in message news:<1x**********@hotpop.com>...
rd******@poncacity.net (Robert Spoons) writes:
Can you look over this code, preferably try it, and comment?
First of all, your code is broken -- in particular some long comment
lines are broken onto the next line :) Please make sure your newsclient
doesn't break lines or post only lines so short that they are not broken.
Javascript code will not survive being wrapped as well as text, and
everybody who wants to try your code must first find and fix the errors
your newsclient has introduced (on a good day, they try, on a bad day,
they move on without commenting at all).
I believe the 'extend' function below will allow you to use full
'class inheritance' in javascript, but I would like to verify it.
Define "full class inheritance". First, define what "class" means in
a Javascript context, where there are no classes.
The extend function allows the following:
1) inheriting from multiple classes,
2) inheriting an inherited classes inheritances (awkward to say),
3) inheriting appended prototype methods and properties of inhertited
classes.
If I read it correctly, it copies the properties of the prototype
of the class and calls(applies) the constructor.
First, code comments:
//If the superclass requires no arguments, [null] must be passed.
Why not the empty array? (or nothing, you should be able to check that)
Object.prototype.extend=function(){
Why not
Function.prototype.extend=function(class,args) {
?
Instead of writing arguments[0] and arguments[1] everywhere?
if(arguments[1]){ //make sure argument(s) are supplied
for(var i=0;i<arguments[1].length;i++){
if(typeof(arguments[1][i])=="string")
arguments[1][i]="'"+arguments[1][i]+"'"
What if the arguement is the Javascript string "a hen's feather"? Or
"String literals use a \\ to write newlines\nYou just write \\n."?
You should also escape quotes, backslashes, special characters (ASCII<32), etc. }
if(arguments[1].length>0){Arguments=arguments[1].join(",")}
else{Arguments=arguments[1][0]}
All this is only necessary if you use eval. Don't use eval. Never use
eval.
for(var i in eval("new arguments[0]("+Arguments+")")){
Use this instead (no eval):
function classCloner () { return class.apply(this,args); };
classCloner.prototype = class.prototype;
var newInstance = new classCloner();
for (var i in newInstance) {
if(i!='extend'){
g=eval("new "+arguments[0]+"("+arguments[1]+")."+i)
Fails if the object has property names like "foo bar" or "2".
Use:
g = newInstance[i];
Then you don't need to create a new object for each property.
if(typeof(g)=="undefined"){
eval("this.prototype."+i+"=new
arguments[0]("+arguments[1]+")."+i)
if g is undefined, you create a new object *the same way* and take
the same property again.
this.prototype[i]=newInstance[i];
}
else{
eval("this.prototype."+i+"=g")
this.prototype[i] = g;
}
}
}
}
}
Ok, my version:
function newApply(class,argsArray) {
function createApply() {
return class.apply(this,argsArray);
}
createApply.prototype = class.prototype;
return new createApply();
}
Function.prototype.extend = function extend(class,argsArray) {
var instance = newApply(class,argsArray);
for (var i in instance) {
if (i != "extend") {
this.prototype[i]=instance[i];
}
}
}
Notice that you don't extend the object with a *class*, but with an
*instance* of the class. Already there, it breaks with how it works in
class based object oriented languages.
... //circle class - a subclassing class
//OBJECTS CAN INHERIT FROM MULTIPLE CLASSES.
function Circle(radius,color){
Circle.extend(Oval,[radius,radius]) //inherits from the more
generic oval class
Circle.extend(Color,[color]) //also inherits from the color class
this.classid="circle"
}
You change the properties of the prototype inside the constructor.
That means that if you create two objects with this constructor,
the second one overwrites the properties of the first ones prototype.
Since they extend with different objects, the result is wrong.
Example
var c1 = new Circle(2,"#ff0000");
var c2 = new Circle(4,"#000000");
alert(c1.color); // gives #000000
Either add the new properties directly to the object being created:
I.e., here:
this.extend(Oval,[radius,radius]);
and in extend:
this[i] = instance[i];
(that is, make objects "inherit" properties from other objects)
or only extend the class once:
Circle10.extend(Oval,[10,10]);
The problem is that you want to make classes inherit from instances.
That really doesn't make much sense, conceptually.
And: if(i!='extend')s+=i+": "+eval("obj."+i)+"\n"
don't use eval:
if(i!='extend')s+=i+": "+obj[i];
<URL:http://jibbering.com/faq/#FAQ4_39>
/L
/*
Lasse Reichstein Nielsen, Thanks for your commentary - it did help.
I will be more specific in the wording I choose.
I still use eval in the function.
Thanks, I've updated the extend function - it addresses all relavent
points you made concerning the origional, and it now acts the way I
desire the function to act.
Also, the new version is much cleaner.
The function will add all publically enumarable properties and methods
of the specified target object to the calling object (effective
inheritance). I have attempted to include example use.
*/
/*
--------------------------
Much cleaner Inheritence function
Use :must be inside of object's constructor
this.extend(new ObjA(args))
(The object Inherits all enumerable properties and methods of ObjA)
*/
// obj is the object instance to inherit from
// i is an Enumerable Property or Method
// insta is a Property or Method Instance
Object.prototype.extend=function(obj){
for(var i in obj){
insta=eval("obj."+i)
eval("this."+i+"=insta")
}
}
/*
--------------------------
*/
function point(x,y){
this.x=x
this.y=y
}
function location(x,y){
this.extend(new point(x,y))
}
location.prototype.moveTo=function(x,y){this.x=x;t his.y=y}
function oval(xrad,yrad){
this.radiusX=xrad
this.radiusY=yrad
}
oval.prototype.meth=function(){alert("ok")}
function circle(rad,color){
this.extend(new oval(rad,rad))
this.color=color
}
circle.prototype.area=function(){return
2*Math.PI*Math.pow(this.radiusX,2)}
function myCircle(rad,color,x,y){
this.extend(new circle(rad,color))
this.extend(new location(x,y))
}
Object.prototype.showProps=function(){
var s=""
for(var i in this)
if(!(i=='extend'||i=='showProps'))s+=i +": "+eval("this."+i)+"\n"
return s
}
a=new myCircle(3,"the hen's blue feather \n",5,10)
b=new myCircle(10,"red",100,120)
c=new oval(4,5)
alert("a\n"+a.showProps()+"\nb\n"+b.showProps()+"\ nc\n"+c.showProps())
alert("a area = "+a.area() +"\nb area = "+b.area())