150 likes | 242 Vues
Learn how to simplify and improve code organization by pulling out common fields into a parent class, implementing getters and setters, and utilizing abstract methods in Java.
E N D
Pulling out a common superclass Barb Ericson Georgia Tech
Common Fields in Bug Classes • BoxBug • Has fields sideLength and steps • SpiralBug • Has fields sideLength and steps • ZBug • Has fields sideLength and steps BoxBug int sideLength int steps SpiralBug int sideLength int steps ZBug int sideLength int steps
Problem • Should add public accessor (getter) and modifiers (setter) methods for each of these fields • Needed in BoxBug • Needed in SpiralBug • Needed in Zbug • This means adding the same code to 3 classes! BoxBug int sideLength int steps SpiralBug int sideLength int steps ZBug int sideLength int steps
A Better Way • Pull out a common parent class with the common fields in it • This is called generalization • PatternBug extends Bug • Has fields of sideLength and steps • Add the getter and setter methods to PatternBug • Change BoxBug, SpiralBug, and ZBug to inherit from PatternBug BoxBug PatternBug SpiralBug int sideLength int steps getSideLength getSteps setSteps setSideLength ZBug
PatternBug • Inherits from Bug • Has the private fields • steps and sideLength • Has public accessors (getters) for the fields • getSteps and getSideLength • Has public modifiers/mutators (setters) for the fields • setSteps and setSideLength
Changes to Bug Subclasses • Subclass PatternBug instead of Bug • Since fields are private we no longer have direct access to the inherited fields • Use getSteps instead of this.steps • Use getSideLength instead of this.sideLength • Use setSteps instead of this.steps = • Use setSideLength instead of this.sideLength =
Challenge • Create the PatternBug class and modify the BoxBug, ZBug, and SpiralBug to inherit from that class instead • Test that the modified classes still work • Turn in the PatternBug class and the modified classes
Breakout Example • If you want the ball to change color to the color of the brick that it hit • You can just add a public getColor method to the Brick class • And then set the ball color to the brick color and call updateImage to redraw the image with the new color • Using the setColor method in Ball
Breakout Classes • Ball inherits from Actor • Has a color • Has a setColor method • Brick inherits from Actor • Has a color • Needs a getColor method • Paddle inherits from Actor • Has a color
Problem • Should add public accessor (getter) and modifiers (setter) methods for the color field to all the classes that have a color field • This means adding the same code to 3 classes! • Could copy the setColor method in Ball to the others • But copying code is tedious and can lead to more fixing if you find an error in the code Brick Color color Ball Color color setColor Paddle Color color
A Better Way • Pull out a common parent class with the common fields in it • This is called generalization • Each of the actors is drawn as an image and has a color • DrawnActor extends Actor • Has a color field • Add the getter and setter methods to DrawnActor • Change Brick, Ball, and Paddle to inherit from DrawnActor Brick DrawnActor Ball Color color getColor setColor updateImage Paddle
Another Problem • setColor calls updateImage to redraw the image of the actor with the new color • Each of Ball, Brick, and Paddle have an updateImage method • But they do something different public void updateImage() { GreenfootImage image = new GreenfootImage(width,width); image.setColor(color); image.fillOval(0,0,width,width); setImage(image); } public void updateImage() { GreenfootImage image = new GreenfootImage(width,height); image.setColor(this.color); image.fillRect(0,0,width,height); setImage(image); } From Ball From Brick
Use abstract! • We can add an abstract method to DrawnActor • Abstract methods can't have any method body public abstract void updateImage(); • This means the class DrawnActor must also be declared abstract public abstract class DrawnActor extends Actor
Abstract Classes • You can not create an object of an abstract class • Can't say new DrawnActor() • Get an error • You can create subclasses of abstract classes • This is what they are used for • The subclasses must provide the body for the methods that are declared abstract or else also be declared abstract • Or you will get a compiler error if you try to compile the class
Challenge • Create a subclass of Actor called DrawnActor • Make it an abstract class • With an abstract method updateImage() • Put in the field color and the setColor and getColor methods • In setColor call updateImage • Modify Brick, Ball, and Paddle to inherit from DrawnActor instead of Actor • Must use setColor and getColor instead of this.color • Will need to cast ((DrawnActor) actor).getColor(); • The compiler only knows that the intersecting actor (brick) is an actor not that it is a DrawnActor so we cast to tell it.