Need help in object oriented programming

Hi,

I am trying to make a round corners script in object oriented programming method. This is purely for learning purposes.

The script is no where near complete but I am already having problems with it.

I am trying out the techniques described in 'David Flanagan ’ text book ‘JavaScript: The Definitive Guide, 5th Edition’

This code is called from html page which once working will place a round container around element

Factory_rounded_corners("content", "#507742", "all_round");

/* content is id of element

  • #507742 is color to be applied
  • all_round means round corners will be applied on top and bottom of element
  • one means only one element is to be affected
    */

**************Javascript functions below *******************


/* Function	Factory_rounded_corners
*	-------------------------
*	Parameter: selector
*	Return: None
*	Description: Create a rounded container around elements to be affected
*/
function Factory_rounded_corners(selector, color, type, numb_elem)
{
	var rounded_container;
	if(numb_elem == "one" && type == "all_round")
	{
                rounded_container = new All_rounded_corners_one_element(selector, color);
		alert(rounded_container.color);[COLOR="#008000"]//works[/COLOR]
		rounded_container.elements_to_be_affected()[COLOR="#FF0000"]//Does not work[/COLOR]
 
	}
}

/* Function	All_rounded_corners_one_element
*	-------------------------
*	Parameter: selector
*	Return: None
*	Description: Create a rounded container around elements to be affected
*/
function All_rounded_corners_one_element(selector, color)
{
	alert("Inside All_rounded_corners");
	this.superclass(selector, color); [COLOR="#008000"]// works[/COLOR]
	//Custom_rounded_container.call(this, selector, color);
}
*	Function custom_rounded_container
*	----------------------------------
*	Parameters: selector
*	Properties: this.temp_array
*	Methods: this.elements_to_be_affected, this.apply
*	Returns: Returns a object 
*	Description: 
*/
function Custom_rounded_container(selector, color)
{
	alert("Inside Custom_rounded_container"); [COLOR="#008000"]// works[/COLOR]
	this.temp_array = selector.split(" ");
	this.color = color;
	//alert(this.temp_array);
}

/*	Function elements_to_be_affected
*	----------------------------------
*	Parameters: None
*	Properties: None
*	Local variables:	None 
*	Local methods: None
*	Returns: elements in array or one element
*	Description: Retrieves elements to be affected
*/
Custom_rounded_container.prototype.elements_to_be_affected = function()
{
	alert("Inside elements_to_be_affected");[COLOR="#FF0000"]//DOES NOT WORK[/COLOR]
}
All_rounded_corners_one_element.prototype.superclass = Custom_rounded_container;
All_rounded_corners_one_element.prototype  = new Custom_rounded_container();

If anyone has a better idea of how to do this, please let me know.

Thankyou

Shippuuden

Here’s the declaration for a constructor:

function Custom_rounded_container(selector, color)

And here’s how that constructor is being called:

All_rounded_corners_one_element.prototype  = new Custom_rounded_container();

Something seems to be missing.

Hi Paul,

Do you mean the arguments?

I didn’t put them in because it wasn’t in the textbook.

I have put the arguments in now and it still doesn’t work.

This is how it looks like now:

All_rounded_corners_one_element.prototype  = new Custom_rounded_container(selector, color);

Which part of the textbook are you referring to?

Let’s explain things a bit better.
Why the code initially didn’t work is because the .split() method was attempting to be used on an undefined object.

this.temp_array = selector.split(" ");

After your update you are passing in a variable called selector, but that’s still undefined.

I have inserted following if statement inside Custom_rounded_container function:


if(selector == undefined)
{
	alert("selector is undefined");
}
else
{
	alert("selector is:		" + " " + selector);
	alert("Inside Custom_rounded_container");
}

You were correct though. When I changed

All_rounded_corners_one_element.prototype  = new Custom_rounded_container(selector, color);

back to

All_rounded_corners_one_element.prototype  = new Custom_rounded_container();

It was showing that the ''selector is undefined"

but when i changed it back to

All_rounded_corners_one_element.prototype  = new Custom_rounded_container(selector, color);

Only the else part of the if statement is executing, it is showing the selector value.

but rounded_container.elements_to_be_affected() is still not working.

That’s good, your updated code must be doing something else than what has already been covered, because when I follow what you have stated, my web browser still shows “Uncaught ReferenceError: selector is not defined”

Could you put up your code at jsfiddle.net so that we can get a better idea of how things currently are?

I have only uploaded the relevant html code.

Let me know if you want rest of the html code as well.

No that’s fine. Where is this line getting the selector from?

Custom_rounded_container(selector, color);

It’s getting it from :


this.superclass(selector, color);


function All_rounded_corners_one_element(selector, color)
{
	alert("Inside All_rounded_corners");
	this.superclass(selector, color);
}

Follow it through - you’ll see that this line doesn’t know about the selector or color variables.

Custom_rounded_container(selector, color);

It does know because when I add


		alert(rounded_container.color);//works
		alert(rounded_container.temp_array);

inside Factory_rounded_corners function


function Factory_rounded_corners(selector, color, type, numb_elem)
{
	var rounded_container;
	if(numb_elem == "one" && type == "all_round")
	{
		rounded_container = new All_rounded_corners_one_element(selector, color);
		alert(rounded_container.color);//[COLOR="#FF0000"]added[/COLOR]
		alert(rounded_container.temp_array); //[COLOR="#FF0000"]added[/COLOR]
		rounded_container.test();
		//rounded_container.elements_to_be_affected();//Does not work
		
	}
}


it is showing correct values.

color and temp_array are both inside Custom_rounded_container

Move those alerts to where they are just before the line of code I pointed out before.

Did you mean before


this.superclass(selector, color);


function All_rounded_corners_one_element(selector, color)
{
	alert("Inside All_rounded_corners");
	alert("color is 	" + " " +color);//works
	alert("selector is 	" + " " + selector);	
	this.superclass(selector, color);
}

It is still showing correct values

No, I mean before this line:

Custom_rounded_container(selector, color);

Umm is this what you meant?

alert(selector);
alert(color);
All_rounded_corners_one_element.prototype = new Custom_rounded_container(selector, color);

Nothing is showing now.

That is correct. That’s one of the causes of the problems you are facing

ok, so what would be the best way to do this?

I want All_rounded_corners_one_element to inherit Custom_rounded_container.

Selector and color needs to be inside Custom_rounded_container because other objects will also inherit Custom_rounded_container.

The book I am following seems to be wrong then.

This is the code in the JavaScript: The Definitive Guide, 5th Edition text book by David Flanagan


// Here is a simple Rectangle class.
// It has a width and height and can compute its own area
function Rectangle(w, h) {
    this.width = w;
    this.height = h;
}
Rectangle.prototype.area = function( ) { return this.width * this.height; }

// Here is how we might subclass it
function PositionedRectangle(x, y, w, h) {
    // First, invoke the superclass constructor on the new object
    // so that it can initialize the width and height.
    // We use the call method so that we invoke the constructor as a
    // method of the object to be initialized.
    // This is called constructor chaining.
    Rectangle.call(this, w, h);

    // Now store the position of the upper-left corner of the rectangle
    this.x = x;
    this.y = y;
}

// If we use the default prototype object that is created when we
// define the PositionedRectangle( ) constructor, we get a subclass of Object.
// To subclass Rectangle, we must explicitly create our prototype object.
PositionedRectangle.prototype = new Rectangle( );

// We create this prototype object for inheritance purposes, but we
// don't actually want to inherit the width and height properties that
// each Rectangle object has, so delete them from the prototype.
delete PositionedRectangle.prototype.width;
delete PositionedRectangle.prototype.height;

// Since the prototype object was created with the Rectangle( ) constructor,
// it has a constructor property that refers to that constructor.  But
// we want PositionedRectangle objects to have a different constructor
// property, so we've got to reassign this default constructor property.
PositionedRectangle.prototype.constructor = PositionedRectangle;

// Now that we've configured the prototype object for our subclass,
// we can add instance methods to it.
PositionedRectangle.prototype.contains = function(x,y) {
    return (x > this.x && x < this.x + this.width &&
            y > this.y && y < this.y + this.height);
}

var r = new PositionedRectangle(2,2,2,2);
print(r.contains(3,3));  // invoke an instance method
print(r.area( ));         // invoke an inherited instance method

// Use the instance fields of the class:
print(r.x + ", " + r.y + ", " + r.width + ", " + r.height);

// Our object is an instance of all 3 of these classes
print(r instanceof PositionedRectangle &&
      r instanceof Rectangle &&
      r instanceof Object);

// Store a reference to our superclass constructor.
PositionedRectangle.prototype.superclass = Rectangle;

With this property defined, the syntax for constructor chaining is simpler:

function PositionedRectangle(x, y, w, h) {
    this.superclass(w,h);
    this.x = x;
    this.y = y;
}



I based my code on the sample code in the text book.

What I notice that seems to be different from what you show from the book, is the second line here.

All_rounded_corners_one_element.prototype.superclass = Custom_rounded_container;
All_rounded_corners_one_element.prototype  = new Custom_rounded_container();

For what reason did you add in that second line?

If I understood the text book correctly, if I want to subclass the parent, I must explicitly create the prototype object.

The parent being Custom_rounded_container.

From the textbook:

// If we use the default prototype object that is created when we
// define the PositionedRectangle( ) constructor, we get a subclass of Object.
// To subclass Rectangle, we must explicitly create our prototype object.

PositionedRectangle.prototype = new Rectangle( );

Notice in the Rectangle constructor how even if the values are undefined which they will be when called with no arguments) that no errors will be thrown since the values being assigned to the object will just be undefined?