// CS U213 Spring 2007 // Lecture 14: February 8, 2007 /* Goals: - Extending classes and overriding methods Introduction: Sometimes it is uselful to represent a special case of our data as a subclass of a more general class. This way we can use a uniform way to manipulate our data and in the same time we are able to treat in a unique way any special case. This can be done by overriding the superclass' s methods inside the new subclass. Let's consider the following example: +-----------------------------+ | Star | +-----------------------------+ +---->|Posn loc | | |int lifespan | | +-----------------------------+ | |Star move() | | |boolean draw(Canvas C) | | |boolean iswithin(int w,int h)| | +-----------------------------+ | +------+ | | Posn |--+ +------+ |int x | |int y | +------+ We want a burned star, e.g. a star with 0 to move faster than a live star. So we implement move as follows: //move a star Star move(){ if lifespan-1>0 return (new Star(new Posn(this.loc.x,this.loc.y+10),this lifespan-1) else return (new BurnedStar(new Posn(this.loc.x,this.loc.y+10)));} We want a burned star to have differnt collor than a live star. So we implement draw as follows: //draw a star boolean draw(Canvas c){ if lifespan>0 return (c.drawDisk(this.loc,3,new Yellow()) else return (c.drawDisk(this.loc,3,new Yellow()))} ------*Alternative approach*----------------- --Use a subclass We can use a subclass of stars to represent a burned Star and thus avoid all the if checking. Let Java worry about that. Let's how we can do that. Check the following class diagram: +-----------------------------+ | Star | +-----------------------------+ +---->|Posn loc | | |int lifespan | | +-----------------------------+ | |Star move() | | |boolean draw(Canvas C) | | +-----------------------------+ | /_\ +------+ | | | Posn |--+ +-----------+ +------+ |BurnedStar | |int x | +-----------+ |int y | | | +------+ +-----------+ | | +-----------+ Now we can implement again the two previous functions: //In Star //move a star Star move(){ if (lifetime-1>0) return new Star(new Posn(this.loc.x,this.loc.y+10),this.lifespan-1); else return new BurnedStar(new Posn(this.loc.x,this.loc.y+10));} //In BurnedStar //move a burned tar Star move(){ return new BurnedStar(new Posn(this.loc.x,this.loc.y+20));} //In Star //draw a star boolean draw(Canvas c){ return c.drawDisk(this.loc,3,new Black());} //In BurnedStar //draw a burned star boolean draw(Canvas c){ return c.drawDisk(this.loc,3,new Yellow());} */ //draw teachpack import draw.*; import colors.*; import geometry.*; // to represent a Star class Star{ Posn loc; int lifetime; Star(Posn loc,int lifetime){ this.loc=loc; this.lifetime=lifetime;} //move a star Star move(){ if (lifetime-1>0) return new Star(new Posn(this.loc.x,this.loc.y+10),this.lifetime-1); else return new BurnedStar(new Posn(this.loc.x,this.loc.y+10));} //draw a star boolean draw(Canvas c){ return (c.drawDisk(this.loc,3,new Yellow()));} } //to represent a BurnedStar class BurnedStar extends Star{ BurnedStar(Posn loc){ super(loc,0);} //move a burned star Star move(){ return new BurnedStar(new Posn(this.loc.x,this.loc.y+20));} //draw a burned star boolean draw(Canvas c){ return (c.drawDisk(this.loc,3,new Black()));} } class Examples{ Canvas board = new Canvas(100,100); Posn a = new Posn(50,15); Star s0=new Star(a,2); Star s1=this.s0.move(); Star s2=this.s1.move(); Star s3=this.s2.move(); boolean init = this.board.show(); boolean show0 = check s0.draw(board) expect true; boolean show1 = check s1.draw(board) expect true; boolean show2 = check s2.draw(board) expect true; boolean show3 = check s3.draw(board) expect true; }