Copyright (c) 1998, 1999 D.L. Bailey * Winter 1999 Part 6 Reusing Classes: Inheritance and Composition
Copyright (c) 1998, 1999 D.L. Bailey2 UML Diagram of the Counter Class Hierarchy (From Part 5) Object Counter LimitedCounter RollOverCounter
Copyright (c) 1998, 1999 D.L. Bailey3 Aside The diagrams that we use to distinguish between references and objects are not part of the UML. Using this notation to depict an entire OO program would result in a cluttered diagram! They are intended for helping visualize low-level details. In UML, a class or an object Our object reference/object notation
Copyright (c) 1998, 1999 D.L. Bailey4 Inheritance: Important Concepts Generalization: common behaviour and attributes are moved up the class hierarchy, where they can be inherited by subclasses
Copyright (c) 1998, 1999 D.L. Bailey5 Inheritance: Important Concepts Specialization: behaviour and attributes that apply to a subset of the subclasses (or only one subclass) are moved down the class hierarchy –also: behaviours inherited from a superclass can be overridden by a subclass
Copyright (c) 1998, 1999 D.L. Bailey6 Inheritance: Important Concepts an is-a relationship exists between superclasses and subclasses; e.g., –a Counter is-a kind of Object –a RolloverCounter is-a kind of Counter inheritance provides many benefits, but is inheritance always the best approach to developing new classes?
Copyright (c) 1998, 1999 D.L. Bailey7 Inheritance Is Not Always the Best Approach... suppose we define a class for representing points: class Point { // see project 1! // Coordinates of the point private double x, y; public Point() {…} public Point(double x, double y) {..}
Copyright (c) 1998, 1999 D.L. Bailey8 The Point Class, Cont’d public void setX(double x) {…} public void setY(double x) {…} public double getX() {…} public double getY() {…} public String toString() {…} public void moveto(double x, double y) { this.x = x; this.y = y; }
Copyright (c) 1998, 1999 D.L. Bailey9 Inheritance Is Not Always the Best Approach... now suppose we want to define a class for representing circles a circle is similar to a point –its center is a point on the x-y plane a circle is different than a point –it has a radius we decide to define class Circle as a subclass of class Point
Copyright (c) 1998, 1999 D.L. Bailey10 Circle Is a Kind-of Point class Circle extends Point { private double radius; public Circle() { super(); radius = 0; }
Copyright (c) 1998, 1999 D.L. Bailey11 Circle Is a Kind-of Point public Circle(double x, double y, double r) { super(x, y); radius = r; } public double getRadius() { return radius; }
Copyright (c) 1998, 1999 D.L. Bailey12 Circle Is a Kind-of Point public void setRadius(double r) { if (r > 0.0) radius = r; else radius = 0.0; }
Copyright (c) 1998, 1999 D.L. Bailey13 Circle Is a Kind-of Point public String toString() { return “Center = ” + “[” + getX() + “, ” + getY() + ”]” + “; Radius = ” + getRadius(); } }
Copyright (c) 1998, 1999 D.L. Bailey14 Using the Circle Class // Create a Circle object with center // [0,0] and radius 0 Circle c1; C = new Circle(); // Create a Circle object with center // [5.1, 3.7] and radius 12.2 Circle c2 = new Circle(5.1, 3.7, 12.2);
Copyright (c) 1998, 1999 D.L. Bailey15 Using the Circle Class // Invoke methods defined in Circle C1.setRadius(4.3); double area = c2.area(); // Invoke methods that Circle inherits // From Point C1.moveTo(-1.2, 8.6); double xCoord = c2.getX(); double yCoord = c2.getY();
Copyright (c) 1998, 1999 D.L. Bailey16 Using the Circle Class // Circle overrides Point's toString() // method System.out.print(c1); // The string ”Center = [-1.2, 8.6]; // Radius = 4.3” is displayed
Copyright (c) 1998, 1999 D.L. Bailey17 UML Diagram of the Class Hierarchy Object Point Circle a Point is-a kind of Object a Circle is-a kind of Point
Copyright (c) 1998, 1999 D.L. Bailey18 A Hierarchy of Classes That Represent Different 2-D Shapes Object Point Circle Rectangle Triangle
Copyright (c) 1998, 1999 D.L. Bailey19 Inheritance Is Not Always the Best Approach... is Point the best superclass for Rectangle and Triangle? a rectangle is normally defined by 2 points (opposite corners) or 4 points (the 4 corners) a triangle is normally defined by 3 points (the vertices) does it make sense to say that a Rectangle is-a Point?
Copyright (c) 1998, 1999 D.L. Bailey20 Evaluating Is-a Relationships does it model a real-world relationship? –a car is-a vehicle Car could be a subclass of Vehicle –a car has an engine, but a car is not an engine Car should not be a subclass of Engine
Copyright (c) 1998, 1999 D.L. Bailey21 Evaluating Is-a Relationships is the class a reasonable superclass for a group of conceptually similar subclasses? –Circle, Triangle and Rectangle are all 2-D shapes –is the is-a relationship with Point equally good for all of these classes?
Copyright (c) 1998, 1999 D.L. Bailey22 Evaluating Is-a Relationships Principle of substitution –is it reasonable to use an instance of the subclass anywhere you would use an instance of the superclass? –if not, maybe is-a is the wrong relationship for the classes
Copyright (c) 1998, 1999 D.L. Bailey23 Class Design by Composition Instead of designing Rectangle, Circle, and Triangle as subclasses of Point, design the classes so that: –a Circle object will contain a reference to a Point object –a Rectangle object will contain references to two Point objects –a Triangle object will contain references to three Point objects
Copyright (c) 1998, 1999 D.L. Bailey24 Has-a Relationships there is now a has-a relationship between Circle and Point, Rectangle and Point, Triangle and Point we say that: –a Circle has-a Point –a Rectangle has-two Points –a Triangle has-three Points
Copyright (c) 1998, 1999 D.L. Bailey25 Class Reuse Through Composition in the code for class Circle (see next slide), notice that: –instance variable center is a reference to a Point object –the constructors allocate a Point object –toString () sends getx() and gety() messages to the Point object to obtain the coordinates of the circle’s center
Copyright (c) 1998, 1999 D.L. Bailey26 Circle Has-a Point class Circle { private Point center; private double radius; public Circle() { center = new Point(0.0, 0.0); radius = 0.0; }
Copyright (c) 1998, 1999 D.L. Bailey27 Circle Has-a Point public Circle(double x, double y, double r) { center = new Point(x, y); radius = r; } public double getRadius() { return radius; }
Copyright (c) 1998, 1999 D.L. Bailey28 Circle Has-a Point public void setRadius(double r) { if (r > 0.0) radius = r; else radius = 0.0; }
Copyright (c) 1998, 1999 D.L. Bailey29 Circle Has-a Point public String toString() { return ”Center = " + "[" + center.getX() + ", " + center.getY() + "]" + "; Radius = " + getRadius(); }
Copyright (c) 1998, 1999 D.L. Bailey30 UML Diagrams CirclePoint 1 the line with the black diamond denotes composite aggregation (a.k.a. has-a): a Circle object has 1 Point object the Point object is part-of exactly one Circle object when the Circle object is destroyed, the Point object is destroyed
Copyright (c) 1998, 1999 D.L. Bailey31 UML Diagrams Rectangle Point 2 Triangle Point 3
Copyright (c) 1998, 1999 D.L. Bailey32 What About getX(), getY(), setX(), setY() and moveTo()? the first (is-a) version of Circle inherited these methods from Point if we want these methods in the second (has-a) version of Circle, we need to add these methods to the Circle class
Copyright (c) 1998, 1999 D.L. Bailey33 Circle.moveTo() the moveTo() method forwards the “move-to” message to the Point object –moving a circle’s center point moves the entire circle public void moveTo(double x, double y) { center.moveTo(x, y); }
Copyright (c) 1998, 1999 D.L. Bailey34 Setters and Getters Circle.setX(), Circle.setY(), Circle.getX(), and Circle.getY() would be similar to Circle.moveTo() –they would forward the message to the Point object
Copyright (c) 1998, 1999 D.L. Bailey35 Designing Class Hierarchies let’s continue the development of the classes that represent 2-D shapes ( Circle, Rectangle, Triangle ) by specifying that 2-D objects must be able to compute and return their area and perimeter –all 2-D shape classes must respond to area() and perimeter() messages
Copyright (c) 1998, 1999 D.L. Bailey36 Designing Class Hierarchies how do we ensure that all the 2-D shape classes provide these behaviours? create a common superclass called TwoDimensionalShape that has area() and perimeter() methods? –but these methods must be overridden in all 2-D shape subclasses - there is no common behaviour that can be inherited
Copyright (c) 1998, 1999 D.L. Bailey37 Abstract Classes abstract class TwoDimensionalShape { abstract public double perimeter(); abstract public double area(); } abstract class TwoDimensionalShape cannot be instantiated the abstract methods do not have implementations
Copyright (c) 1998, 1999 D.L. Bailey38 Abstract Classes the intent is that one or more concrete subclasses will be derived from TwoDimensionalShape each concrete subclass of TwoDimensionalShape must define the area() and perimeter() methods we can create instances of concrete subclasses
Copyright (c) 1998, 1999 D.L. Bailey39 Hierarchy of 2-d-shape Classes Object TwoDimensionalShape Circle Rectangle Triangle Italicized name denotes abstract class
Copyright (c) 1998, 1999 D.L. Bailey40 Class Circle class Circle extends TwoDimensionalShape { // The body of this class is identical // to the has-a version of Circle, // but also defines the perimeter() // and area() methods. }
Copyright (c) 1998, 1999 D.L. Bailey41 Concrete Implementations of Abstract Methods (in Circle) public double area() { return java.lang.Math.PI * getRadius() * getRadius(); } public double perimeter() { return 2 * java.lang.Math.PI * getRadius(); }
Copyright (c) 1998, 1999 D.L. Bailey42 Class Circle if we don’t define perimeter() and area() methods, the compiler will remind us to define them or redeclare Circle as an abstract class (in which case we can’t create Circle objects) similarly, the Triangle and Rectangle classes must define perimeter() and area() methods
Copyright (c) 1998, 1999 D.L. Bailey43 Designing Class Hierarchies suppose we want to develop a group of classes that represent 3-D shapes (Cylinder, Cone, Cube, Pyramid) all 3-D objects must be able to compute and return their surface area and volume –all 3-D shape classes must respond to area() and volume() messages
Copyright (c) 1998, 1999 D.L. Bailey44 Designing Class Hierarchies make the 3-D shape classes subclasses of the corresponding 2-D shape classes the 2-D shape classes are unchanged (each class is composed of at least one Point ) add an abstract method perimeter() to abstract class Shape (formerly TwoDimensionalShape)
Copyright (c) 1998, 1999 D.L. Bailey45 UML Diagram Shape Circle Rectangle Triangle Cylinder Cone Pyramid Cube
Copyright (c) 1998, 1999 D.L. Bailey46 Abstract Class Shape abstract class Shape { abstract public double perimeter(); abstract public double area(); abstract public double volume(); } all 2-D and 3-D classes must implement these methods –for 2-D shapes, volume() will always return 0 –but, what is the perimeter of a 3-D shape?
Copyright (c) 1998, 1999 D.L. Bailey47 Class Cylinder class Cylinder extends Circle { private double height; public Cylinder() { super(); height = 0.0; }
Copyright (c) 1998, 1999 D.L. Bailey48 Class Cylinder public Cylinder(double x, double y, double r, double h) { super(x, y, r); height = h; } public double getHeight() { return height; }
Copyright (c) 1998, 1999 D.L. Bailey49 Class Cylinder public void setHeight(double h) { if (h > 0.0) height = h; else height = 0.0; }
Copyright (c) 1998, 1999 D.L. Bailey50 Class Cylinder public double area() { return 2 * super.area() + height * super.perimeter(); } public double volume() { return super.area() * height; }
Copyright (c) 1998, 1999 D.L. Bailey51 Class Cylinder // Inherits perimeter from Circle. // Should we define a perimeter // method that throws an exception? // What is the perimeter of a 3-D // Shape? public String toString() { return super.toString() + "; Height = " + height; }
Copyright (c) 1998, 1999 D.L. Bailey52 Discussion look at the the is-a relationships between the 2-D and 3-D shape classes –does “a cylinder is-a circle” accurately model the real world? –we should also consider has-a relationships perimeter() is easy to implement in the 2-D shape classes, but how should we override it in the 3-D shape classes?
Copyright (c) 1998, 1999 D.L. Bailey53 Second Attempt at a Class Hierarchy split the abstract methods among three abstract classes develop two parallel concrete class hierarchies –one for 2-D shape classes –one for 3-D shape classes 3-D objects will be composed of one or more 2-D objects
Copyright (c) 1998, 1999 D.L. Bailey54 UML Diagram for the Abstract Classes Shape TwoDimensionalShape ThreeDimensionalShape
Copyright (c) 1998, 1999 D.L. Bailey55 Abstract Classes for the Shapes Hierarchy abstract class shape { // These will be implemented by all // classes that represent shapes abstract public double area(); abstract public double volume(); }
Copyright (c) 1998, 1999 D.L. Bailey56 Abstract Classes for the Shapes Hierarchy abstract class TwoDimensionalShape extends Shape { // This will be implemented by all // classes that represent 2-D shapes abstract public double perimeter(); }
Copyright (c) 1998, 1999 D.L. Bailey57 Abstract Classes for the Shapes Hierarchy abstract class ThreeDimensionalShape extends Shape { // Any abstract methods?? // Is it just a placeholder for now? }
Copyright (c) 1998, 1999 D.L. Bailey58 UML Diagram for the 2-D Shape Classes TwoDimensionalShape Circle Rectangle Triangle each 2-D shape object contains one or more Point objects
Copyright (c) 1998, 1999 D.L. Bailey59 UML Diagram for the 3-D Shape Classes ThreeDimensionalShape Cylinder Pyramid Cone Rectangle Cube Circle Rectangle Circle Triangle
Copyright (c) 1998, 1999 D.L. Bailey60 More About Abstract Classes an abstract class can have instance variables and instance methods an abstract class can have class ( static ) variables and methods
Copyright (c) 1998, 1999 D.L. Bailey61 More About Abstract Classes for example, we could define class Shape this way: abstract class Shape { abstract public double area(); public double volume() { return 0.0; }
Copyright (c) 1998, 1999 D.L. Bailey62 More About Abstract Classes all 2-D classes inherit volume() –makes sense - the volume of a 2-D object is always 0 all 3-D classes override volume() exercise for the student: implement the complete class hierarchy that has just been presented
Copyright (c) 1998, 1999 D.L. Bailey63 More About Abstract Classes an abstract class does not need to have any abstract methods (although it usually will) if a subclass of an abstract class does not override all of the abstract methods in the abstract class, then the subclass must also be declared abstract
Copyright (c) 1998, 1999 D.L. Bailey64 Interfaces interface - a collection of constants and abstract methods unlike abstract classes, an interface cannot have instance variables or methods, class variables or methods interfaces are not classes –we cannot create instances of an interface
Copyright (c) 1998, 1999 D.L. Bailey65 Interfaces an interface is used to specify the interface (the methods) that a class must implement an interface can also be used to define constants that a class (hierarchy) can use
Copyright (c) 1998, 1999 D.L. Bailey66 Interfaces interface Shape { double area(); double volume(); } each of the methods is automatically public and abstract –no other modifiers are permitted
Copyright (c) 1998, 1999 D.L. Bailey67 Interface Inheritance interfaces can be arranged in an interface hierarchy: interface TwoDimensionalShape extends Shape { double perimeter(); } TwoDimensionalShape inherits the abstract methods defined by Shape
Copyright (c) 1998, 1999 D.L. Bailey68 Interface Implementation class Circle implements TwoDimensionalShape {... } Circle must implement (provide bodies for) perimeter(), area(), and volume()
Copyright (c) 1998, 1999 D.L. Bailey69 UML Notation for Interfaces Shape TwoDimensionalShape ThreeDimensionalShape
Copyright (c) 1998, 1999 D.L. Bailey70 UML Notation for Classes That Implement the Shape Interfaces TwoDimensionalShape Circle Rectangle Triangle each 2-D object contains one or more Point objects (not depicted here)
Copyright (c) 1998, 1999 D.L. Bailey71 UML Notation for Classes That Implement the Shape Interfaces ThreeDimensionalShape Cylinder Pyramid Cone Rectangle Cube Circle Rectangle Circle Triangle
Copyright (c) 1998, 1999 D.L. Bailey72 Interfaces: General Form interface I1 { // I2 defines constants and abstract // methods } interface I2 extends I1 { // I2 inherits constants and abstract // methods from I1 // I2 defines additional constants and // abstract methods } …also, interface I3 {…}
Copyright (c) 1998, 1999 D.L. Bailey73 Interface Implementation: General Form class C1 {/* variables and methods */} class C2 extends C1 implements I2, I3 { // C2 inherits variables and methods // from C1 // C2 defines additional variables and // methods // C2 defines all methods specified by // I1, I2, and I3 }
Copyright (c) 1998, 1999 D.L. Bailey74 Extending a Class vs. Implementing an Interface a class can directly extend at most one concrete superclass or one abstract superclass –no multiple inheritance in Java a class can implement any number of interfaces more on interfaces when we look at polymorphism and how classes can represent multiple types