CIS3023: Programming Fundamentals for CIS Majors II Summer 2010 Abstract Classes “None of the abstract concepts comes closer to fulfilled utopia than that of eternal peace.” --Theodor W. Adorno Course Lecture Slides 7 June 2010 Ganesh Viswanathan Example Drawing Application Create different shapes: circle, rectangle, … Circle Rectangle -color: String -color: String -filled: Boolean -filled: Boolean -dateCreated: java.util.Date -dateCreated: java.util.Date -radius: double -width: double +Circle() -height: double +Circle(radius: double) +Rectangle() +getRadius(): double +Rectangle(width: double, height: double) +setRadius(radius: double): void +getWidth(): double +getColor(): String +setWidth(width: double): void +setColor(color: String): void +getHeight(): double +isFilled(): boolean +getColor(): String +setFilled(filled: boolean): void +setColor(color: String): void +getDateCreated(): java.util.Date +isFilled(): boolean +setFilled(filled: boolean): void +getArea(): double +getDateCreated(): java.util.Date +getPerimeter(): double +getDiameter(): double +setHeight(height: double): void +getArea(): double +getPerimeter(): double G e o m e tr ic O b j e c t - c o lo r : S t r i n g T h e c o lo r o f t h e o b j e c t (d e f a u lt : w h i t e ) . - f i ll e d : b o o le a n In d i c a t e s w h e t h e r t h e o b j e c t i s fi lle d w i t h a c o lo r ( d e f a u lt : f a ls e ) . - d a t e C r e a t e d : j a v a .u t i l.D a t e T h e d a t e w h e n th e o b j e c t w a s c r e a t e d . + G e o m e tric O b je c t() C re a te s a G e o m e tric O b je c t. + g e t C o lo r ( ) : S t r i n g R e t u rn s th e c o lo r . + s e t C o lo r ( c o l o r : S t r i n g ) : v o i d S e ts a n e w c o lo r. + i s F i lle d ( ) : b o o le a n R e t u rn s th e f i lle d p r o p e r t y . + s e t F i ll e d ( f i ll e d : b o o le a n ) : v o i d S e t s a n e w f i l le d p r o p e r t y . + g e t D a t e C r e a t e d ( ) : j a v a .u t i l.D a t e R e t u rn s th e d a t e C r e a t e d . + t o S t r in g ( ) : S t r i n g R e t u rn s a s t r in g r e p r e s e n t a t i o n o f th i s o b j e c t . R e c ta n g le C ir c le - r a d iu s : d o u b le + C i rc le ( ) - w i d t h : d o u b le - h e i g h t : d o u b le + C i rc le ( r a d i u s : d o u b le ) + R e c ta n g le ( ) + g e t R a d iu s ( ) : d o u b le + R e c ta n g le ( w i d th : d o u b le , h e i g h t : d o u b le ) + s e t R a d iu s ( r a d iu s : d o u b le ) : v o i d + g e t W i d t h ( ) : d o u b le + g e t A r e a ( ) : d o u b le + s e t W i d th ( w i d th : d o u b le ) : v o i d + g e t P e r i m e t e r ( ) : d o u b le + g e t H e i g h t ( ) : d o u b le + g e t D i a m e t e r ( ) : d o u b le + s e t H e i g h t ( h e i g h t : d o u b le ) : v o i d + g e t A r e a ( ) : d o u b le + g e t P e r i m e t e r ( ) : d o u b le So now we can instantiate a GeometricObject as follows: GeometricObject g = new GeometricObject(); But does it make sense ? Solution – Abstract Classes! Do not allow instantiation of GeometricObject class How? Declare it as abstract as follows: public abstract class GeometricObject { … } 6 Abstract Class G e o m e tr ic O b j e c t - c o lo r : S t r i n g T h e c o lo r o f t h e o b j e c t (d e f a u lt : w h i t e ) . - f i ll e d : b o o le a n In d i c a t e s w h e t h e r t h e o b j e c t i s fi lle d w i t h a c o lo r ( d e f a u lt : f a ls e ) . - d a t e C r e a t e d : j a v a .u t i l.D a t e T h e d a t e w h e n th e o b j e c t w a s c r e a t e d . + G e o m e tric O b je c t() C re a te s a G e o m e tric O b je c t. + g e t C o lo r ( ) : S t r i n g R e t u rn s th e c o lo r . + s e t C o lo r ( c o l o r : S t r i n g ) : v o i d S e ts a n e w c o lo r. + i s F i lle d ( ) : b o o le a n R e t u rn s th e f i lle d p r o p e r t y . + s e t F i ll e d ( f i ll e d : b o o le a n ) : v o i d S e t s a n e w f i l le d p r o p e r t y . + g e t D a t e C r e a t e d ( ) : j a v a .u t i l.D a t e R e t u rn s th e d a t e C r e a t e d . + t o S t r in g ( ) : S t r i n g R e t u rn s a s t r in g r e p r e s e n t a t i o n o f th i s o b j e c t . R e c ta n g le C ir c le - r a d iu s : d o u b le + C i rc le ( ) - w i d t h : d o u b le - h e i g h t : d o u b le + C i rc le ( r a d i u s : d o u b le ) + R e c ta n g le ( ) + g e t R a d iu s ( ) : d o u b le + R e c ta n g le ( w i d th : d o u b le , h e i g h t : d o u b le ) + s e t R a d iu s ( r a d iu s : d o u b le ) : v o i d + g e t W i d t h ( ) : d o u b le + g e t A r e a ( ) : d o u b le + s e t W i d th ( w i d th : d o u b le ) : v o i d + g e t P e r i m e t e r ( ) : d o u b le + g e t H e i g h t ( ) : d o u b le + g e t D i a m e t e r ( ) : d o u b le + s e t H e i g h t ( h e i g h t : d o u b le ) : v o i d + g e t A r e a ( ) : d o u b le + g e t P e r i m e t e r ( ) : d o u b le Want to add methods to compute area and perimeter of any GeometricObject Abstract Class G e o m e tr ic O b j e c t - c o lo r : S t r i n g T h e c o lo r o f t h e o b j e c t (d e f a u lt : w h i t e ) . - f i ll e d : b o o le a n In d i c a t e s w h e t h e r t h e o b j e c t i s fi lle d w i t h a c o lo r ( d e f a u lt : f a ls e ) . - d a t e C r e a t e d : j a v a .u t i l.D a t e T h e d a t e w h e n th e o b j e c t w a s c r e a t e d . + G e o m e tric O b je c t() C re a te s a G e o m e tric O b je c t. + g e t C o lo r ( ) : S t r i n g R e t u rn s th e c o lo r . + s e t C o lo r ( c o l o r : S t r i n g ) : v o i d S e ts a n e w c o lo r. + i s F i lle d ( ) : b o o le a n R e t u rn s th e f i lle d p r o p e r t y . + s e t F i ll e d ( f i ll e d : b o o le a n ) : v o i d S e t s a n e w f i l le d p r o p e r t y . + g e t D a t e C r e a t e d ( ) : j a v a .u t i l.D a t e R e t u rn s th e d a t e C r e a t e d . + t o S t r in g ( ) : S t r i n g R e t u rn s a s t r in g r e p r e s e n t a t i o n o f th i s o b j e c t . R e c ta n g le C ir c le - r a d iu s : d o u b le + C i rc le ( ) Added methods to compute area and perimeter for any GeometricObject! - w i d t h : d o u b le - h e i g h t : d o u b le + C i rc le ( r a d i u s : d o u b le ) + R e c ta n g le ( ) + g e t R a d iu s ( ) : d o u b le + R e c ta n g le ( w i d th : d o u b le , h e i g h t : d o u b le ) + s e t R a d iu s ( r a d iu s : d o u b le ) : v o i d + g e t W i d t h ( ) : d o u b le + g e t A r e a ( ) : d o u b le + s e t W i d th ( w i d th : d o u b le ) : v o i d + g e t P e r i m e t e r ( ) : d o u b le + g e t H e i g h t ( ) : d o u b le + g e t D i a m e t e r ( ) : d o u b le + s e t H e i g h t ( h e i g h t : d o u b le ) : v o i d + g e t A r e a ( ) : d o u b le + g e t P e r i m e t e r ( ) : d o u b le 8 public abstract class GeometricObject { private String color = "white"; private boolean filled; protected GeometricObject() { filled = false; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public boolean isFilled() { return filled; } public void setFilled(boolean filled) { this.filled = filled; } public String toString() { return "color: " + color + " and filled: " + filled; } } 9 public class Circle extends GeometricObject { private double radius; public Circle() { radius = 1.0; } public Circle(double radius) { this.radius = radius; public double getRadius() { return radius; public void setRadius(double radius) { this.radius = radius; } } } public double getArea() { return radius * radius * Math.PI; } public double getPerimeter() { return 2 * radius * Math.PI; } } 10 public class Rectangle extends GeometricObject { private double width; private double height; public Rectangle() { width = 1.0; height = 1.0; } public Rectangle(double width, double height) { this.width = width; this.height = height; } public double getWidth() { return width; } public void setWidth(double w){ width = w; } public double getHeight() { return height; } public void setHeight(double h) { height = h; } public double getArea() { return width * height; } public double getPerimeter() { return 2 * (width + height); } } 11 public class Main { public static void main(String[] args) { GeometricObject[] objects = new GeometricObject[5]; objects[0] = new Circle(5); objects[1] = new Rectangle(5, 3); for(int i = 0; i < objects.length; i++){ if(objects[i] != null) System.out.println("Area: " + objects[i].getArea() + "Perimeter: " + objects[i].getPerimeter()); } } } Will give error!! cannot find symbol: getArea( ) and getPerimeter( ) public abstract class GeometricObject { private String color = "white"; private boolean filled; Solution protected GeometricObject() { filled = false; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public boolean isFilled() { return filled; } public void setFilled(boolean filled) { this.filled = filled; } public String toString() { return "color: " + color + " and filled: " + filled; } public abstract double getArea(); public abstract double getPerimeter(); } 13 public class Main { public static void main(String[] args) { GeometricObject[] objects = new GeometricObject[5]; objects[0] = new Circle(5); objects[1] = new Rectangle(5, 3); for(int i = 0; i < objects.length; i++){ if(objects[i] != null) System.out.println("Area: " + objects[i].getArea() + "Perimeter: " + objects[i].getPerimeter()); } } } Will compile successfully now! public abstract class GeometricObject { private String color = "white"; private boolean filled; protected GeometricObject() { filled = false; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } Why not create concrete getArea( ) and getPerimeter( ) methods with no bodies?? public boolean isFilled() { return filled; } public void setFilled(boolean filled) { this.filled = filled; } public String toString() { return "color: " + color + " and filled: " + filled; } public double getArea() { return 0; } public double getPerimeter { return 0; } } 15 Abstract Class Characteristics • A class that contains abstract methods must be abstract. • However, it is possible to declare an abstract class that contains no abstract methods. • A subclass can be abstract even if its superclass is concrete. 16 Abstract Class, contd. • All derived classes of an abstract class will have to implement its abstract method(s), or they too will be abstract • An abstract class cannot be instantiated • An abstract class can be used as a data type though. GeometricObject g; GeometricObject[] geo = new GeometricObject[10]; 17 Why is the following allowed? GeometricObject[] geo = new GeometricObject[10]; Why allow abstract classes to be used as data types if they can not be instantiated? 18 public class Main { public static void main(String[] args) { GeometricObject[] objects = new GeometricObject[5]; objects[0] = new Circle(5); objects[1] = new Rectangle(5, 3); for(int i = 0; i < objects.length; i++){ if(objects[i] != null) System.out.println("Area: " + objects[i].getArea() + "Perimeter: " + objects[i].getPerimeter()); } } } Allows you to take advantage of polymorphism! 19 public class TestGeometricObject { public static void main(String[] args) { Circle c = new Circle(5); Rectangle r1 = new Rectangle(5, 3); Rectangle r2 = new Rectangle(3, 3); System.out.println(“c and r1 have equal area: " + equalArea(c, r1)); System.out.println(“r1 and r2 have equal area: " + equalArea(r1, r2)); } // what should the definition of equalArea() look like? public static boolean equalArea( ? obj1, ? obj2) { return obj1.getArea() == obj2.getArea(); } } 20 public class TestGeometricObject { Option 1 public static void main(String[] args) { Circle c = new Circle(5); Rectangle r1 = new Rectangle(5, 3); Rectangle r2 = new Rectangle(3, 3); System.out.println(“c and r1 have equal area: " + equalArea(c, r1)); System.out.println(“r1 and r2 have equal area: " + equalArea(r1, r2)); } // what should the definition of equalArea() look like? public static boolean equalArea( Circle o1, Rectangle o2){ return o1.getArea() == o2.getArea(); } public static boolean equalArea( Rectangle o1, Rectangle o2){ return o1.getArea() == o2.getArea(); 21 } public class TestGeometricObject { public static void main(String[] args) { Circle c = new Circle(5); Rectangle r1 = new Rectangle(5, 3); Rectangle r2 = new Rectangle(3, 3); System.out.println(“c and r1 have equal area: " + equalArea(c, r1)); System.out.println(“r1 and r2 have equal area: " + equalArea(r1, r2)); } public static boolean equalArea(GeometricObject obj1, GeometricObject obj2) { return obj1.getArea() == obj2.getArea(); } } 22 public class TestGeometricObject { public static void main(String[] args) { GeometricObject geoObject1 = new Circle(5); GeometricObject geoObject2 = new Rectangle(5, 3); System.out.println(“geoObject1 and geoObject2 have area: " + equalArea(geoObject1, geoObject2)); System.out.println(“geoObject2 and geoObject3 have area: " + equalArea(geoObject2, geoObject3)); } public static boolean equalArea(Object obj1, Object obj2) { // why not declare the parameters as Object type? return obj1.getArea() == obj2.getArea(); } } Will give an error as Object class has no getArea( ) method! 23 public class TestGeometricObject { public static void main(String[] args) { GeometricObject geoObject1 = new Circle(5); GeometricObject geoObject2 = new Rectangle(5, 3); System.out.println(“geoObject1 and geoObject2 have area: " + equalArea(geoObject1, geoObject2)); System.out.println(“geoObject2 and geoObject3 have area: " + equalArea(geoObject2, geoObject3)); } public static boolean equalArea(Object obj1, Object obj2) { // why not declare the parameters as Object type? GeometricObject g1 = (GeometricObject)obj1; GeometricObject g2 = (GeometricObject)obj2; return g1.getArea() == g2.getArea(); } } 24 Get more info! http://java.sun.com/docs/books/tutorial/java/IandI/abstract.html http://mindprod.com/jgloss/interfacevsabstract.html