## Object-Oriented Design & Patterns

#### Cay S. Horstmann

### Chapter 6

### Inheritance and Abstract Classes

## Chapter Topics

- The Concept of Inheritance
- Graphics Programming with Inheritance
- Abstract Classes
- The TEMPLATE METHOD Pattern
- Protected Interfaces
- The Hierarchy of Swing Components
- The Hierarchy of Standard Geometrical Shapes
- The Hierarchy of Exception Classes
- When Not to Use Inheritance

## Modeling Specialization

- Start with simple Employee class
  public class Employee
  {
  public Employee(String aName) { name = aName; }
  public void setSalary(double aSalary) { salary = aSalary; }
  public String getName() { return name; }
  public double getSalary() { return salary; }
  private String name;
  private double salary;
  }
- Manager is a subclass

## Modeling Specialization

- Manager class adds new method: setBonus
- Manager class overrides existing method: getSalary
- Adds salary and bonus
- public class Manager extends Employee
  {
  public Manager(String aName) { ... }
  public void setBonus(double aBonus) { bonus = aBonus; } // new method
  public double getSalary() { ... } // overrides Employee method
  private double bonus; // new field
  }

## Modeling Specialization

## Manager Methods and Fields

- methods setSalary, getname (inherited from Employee)
- method getSalary (overridden in Manager)
- method setBonus (defined in Manager)
- fields name and salary (defined in Employee)
- field bonus (defined in Manager)

## The Super/Sub Terminology

- Why is Manager a subclass?
- Isn't a Manager superior?
- Doesn't a Manager object have more fields?
- The set of managers is a subset of the set of employees

## The Super/Sub Terminology

## Inheritance Hierarchies

- Real world: Hierarchies describe general/specific relationships

- General concept at root of tree
- More specific concepts are children

- Programming: Inheritance hierarchy

- General superclass at root of tree
- More specific subclasses are children

## Inheritance Hierarchies

## The Substitution Principle

- Formulated by Barbara Liskov
- You can use a subclass object whenever a superclass object is expected
- Example:
  Employee e;
  ...
  System.out.println("salary=" + e.getSalary());
- Can set e to Manager reference
- Polymorphism: Correct getSalary method is invoked

## Invoking Superclass Methods

- Can't access private fields of superclass
  public class Manager extends Employee
  {
  public double getSalary()
  {
  return salary + bonus; // ERROR--private field
  }
  ...
  }
- Be careful when calling superclass method
  public double getSalary()
  {
  return getSalary() + bonus; // ERROR--recursive call
  }

## Invoking Superclass Methods

- Use super keyword
  public double getSalary()
  {
  return super.getSalary() + bonus;
  }
- super is not a reference
- super turns off polymorphic call mechanism

## Invoking Superclass Constructors

- Use `super` keyword in subclass constructor:
  public Manager(String aName)
  {
  super(aName); // calls superclass constructor
  bonus = 0;
  }
- Call to `super` must be first statement in subclass constructor
- If subclass constructor doesn't call `super`, superclass must have constructor without parameters

## Preconditions

- Precondition of redefined method at most as strong

-     public class Employee
      {
         /**
            Sets the employee salary to a given value.
            @param aSalary the new salary
            @precondition aSalary > 0
         */
         public void setSalary(double aSalary) { ... }
      }

- Can we redefine `Manager.setSalary` with precondition
  `salary > 100000`?
- No--Could be defeated:

      Manager m = new Manager();
      Employee e = m;
      e.setSalary(50000);

## Postconditions, Visibility, Exceptions

- Postcondition of redefined method at least as strong
- Example: Employee.setSalary promises not to decrease salary
- Then Manager.setSalary must fulfill postcondition
- Redefined method cannot be more `private`.
  (Common error: omit `public` when redefining)
- Redefined method cannot throw more checked exceptions

## Graphic Programming with Inheritance

- Chapter 4: Create drawings by by implementing Icon interface type
- Now: Form subclass of JPanel
  public class MyPanel extends JPanel
  {
  public void paintComponent(Graphics g)
  {
  drawing instructions go here
  }
  ...
  }
- Advantage: Inherit behavior from JPanel
- Example: Can attach mouse listener to JPanel

## Overriding paintComponent

- Draw a car:
  public class MyPanel extends JPanel
  {
  public void paintComponent(Graphics g)
  {
  Graphics2D g2 = (Graphics2D)g;
  car.draw(g2);
  }
  ...
  }
- Problem: Screen is corrupted when moving frame
- Remedy: call super.paintComponent(g)

## Overriding paintComponent

## Mouse Listeners

- Attach mouse listener to component
- Can listen to mouse events (clicks) or mouse motion events

      public interface MouseListener
      {
         void mouseClicked(MouseEvent event);
         void mousePressed(MouseEvent event);
         void mouseReleased(MouseEvent event);
         void mouseEntered(MouseEvent event);
         void mouseExited(MouseEvent event);
      }

      public interface MouseMotionListener
      {
         void mouseMoved(MouseEvent event);
         void mouseDragged(MouseEvent event);
      }

## Mouse Adapters

- What if you just want to listen to `mousePressed?`
- Extend `MouseAdapter
  `

      public class MouseAdapter implements MouseListener
      {
         public void mouseClicked(MouseEvent event) {}
         public void mousePressed(MouseEvent event) {}
         public void mouseReleased(MouseEvent event) {}
         public void mouseEntered(MouseEvent event) {}
         public void mouseExited(MouseEvent event) {}
      }

- Component constructor adds listener:

      addMouseListener(new
         MouseAdapter()
         {
            public void mousePressed(MouseEvent event)
            {
               mouse action goes here
            }
         });

## Car Mover Program

- Use the mouse to drag a car shape
- Car panel has mouse + mouse motion listeners
- mousePressed remembers point of mouse press
- mouseDragged translates car shape
- Ch6/car/CarPanel.java
- Ch6/car/CarMover.java
- Ch6/car/CarShape.java

## Car Mover Program

## Scene Editor

- Draws various shapes
- User can add, delete, move shapes
- User selects shape with mouse
- Selected shape is highlighted (filled in)

## Scene Editor

## The SceneShape Interface Type

- keep track of selection state
- draw plain or selected shape
- move shape
- hit testing: is a point (e.g. mouse position) inside?

## The SceneShape Interface Type

public interface SceneShape
{
void setSelected(boolean b);
boolean isSelected();
void draw(Graphics2D g2);
void drawSelection(Graphics2D g2);
void translate(double dx, double dy);
boolean contains(Point2D aPoint);
}

## CarShape and HouseShape Classes

    public class CarShape implements SceneShape
    {
       ...
       public void setSelected(boolean b) { selected = b; }
       public boolean isSelected() { return selected; }
       private boolean selected;
    }

    public class HouseShape implements SceneShape
    {
       ...
       public void setSelected(boolean b) { selected = b; }
       public boolean isSelected() { return selected; }
       private boolean selected;
    }

## Abstract Classes

- Factor out common behavior
  (setSelected, isSelected)
- Subclasses inherit common behavior
- Some methods still undefined
  (draw, drawSelection, translate, contains)

    public class SelectableShape implements Item
    {
       public void setSelected(boolean b) { selected = b; }
       public boolean isSelected() { return selected; }
       private boolean selected;
    }

## Abstract Classes

- `SelectableShape` doesn't define all `SceneShape` methods
- It's abstract
- `public abstract class SelectableShape implements SceneShape`
- `HouseShape` and `CarShape` are concrete
- Can't instantiate abstract class:

      SelectableShape s = new SelectableShape(); // NO

- Ok to have variables of abstract class type:

      SelectableShape s = new HouseShape(); // OK

## Abstract Classes and Interface Types

- Abstract classes can have fields
- Interface types can only have constants (`public static final`)
- Abstract classes can define methods
- Interface types can only declare methods
- A class can implement any number of interface types
- In Java, a class can extend only one other class

## Scene Editor

- Mouse listener selects/unselects item
- Mouse motion listener drags item
- Remove button removes selected items
- Ch6/scene1/ScenePanel.java
- Ch6/scene1/SceneEditor.java
- Ch6/scene1/HouseShape.java

## Uniform Highlighting Technique

- Old approach: each shape draws its selection state
- Inconsistent
- Better approach: shift, draw, shift, draw, restore to original position
- Define in `SelectableShape
  ` `public void drawSelection(Graphics2D g2)
  {
  translate(1, 1);
  draw(g2);
  translate(1, 1);
  draw(g2);
  translate(-2, -2);
  }`

## Uniform Highlighting Technique

## Template Method

- `drawSelection` calls draw
- Must declare draw in SelectableShape
- No implementation at that level!
- Declare as abstract method`
  public abstract void draw(Graphics2D g2)`
- Defined in `CarShape`, `HouseShape`
- `drawSelection` method calls `draw`, `translate`
- `drawSelection` doesn't know which methods--polymorphism
- `draw` Selection is a template method
- Ch6/scene2/SelectableShape.java
- Ch6/scene2/HouseShape.java

## TEMPLATE METHOD Pattern

### Context

1. An algorithm is applicable for multiple types.
2. The algorithm can be broken down into primitive operations. The primitive operations can be different for each type
3. The order of the primitive operations doesn't depend on the type

## TEMPLATE METHOD Pattern

### Solution

1. Define a superclass that has a method for the algorithm and abstract methods for the primitive operations.
2. Implement the algorithm to call the primitive operations in the appropriate order.
3. Do not define the primitive operations in the superclass, or define them to have appropriate default behavior.
4. Each subclass defines the primitive operations but not the algorithm.

## TEMPLATE METHOD Pattern

Name in Design Pattern | Actual Name (Selectable shapes)
AbstractClass | SelectableShape
ConcreteClass | CarShape, HouseShape
templateMethod() | drawSelection
primitiveOp1(), primitiveOp2() | translate, draw

## Compound Shapes

- GeneralPath: sequence of shapes

      GeneralPath path = new GeneralPath();
      path.append(new Rectangle(...), false);
      path.append(new Triangle(...), false);
      g2.draw(path);

- Advantage: Containment test is free
  `path.contains(aPoint);`
- Ch6/scene3/CompoundShape.java
- Ch6/scene3/HouseShape.java

## Compound Shapes

## Access to Superclass Features

- Why does the `HouseShape` constructor call `add`?

      public HouseShape()
      {
         add(new Rectangle(...));
         add(new Triangle(...));
      }

- Why not just
  `path.append(new Rectangle(...));`
- `HouseShape` inherits `path` field
- `HouseShape` can't access `path`
- `path` is private to superclass

## Protected Access

- Make CompoundShape.add method protected
- Protects HouseShape: other classes can't add graffiti
- Protected features can be accessed by subclass methods...
- ...and by methods in the same package
- Bad idea to make fields protected
  `protected GeneralPath path; // DON'T`
- Ok to make methods protected
  `protected void add(Shape s) // GOOD`
- Protected interface separate from public interface

## Hierarchy of Swing Components

- Base of hierarchy: `Component`
- Huge number of common methods:

      int getWidth()
      int getHeight()
      Dimension getPreferredSize()
      void setBackground(Color c)
      . . .

- Most important subclass: `Container`

## Hierarchy of Swing Components

- History: First came AWT, Abstract Window Toolkit
- Used native components
- Subtle platform inconsistencies
- Write once, run anywhere ->
  Write once, debug everywhere
- Swing paints components onto blank windows
- Supports multiple look and feel implementations

## Look and Feel

## Hierarchy of Swing Components

- Base of Swing components: `JComponent`
- Subclass of `Container`
- Some Swing components are containers
- Java has no multiple inheritance
- `JLabel`, `JPanel`, ... are subclasses of `JComponent`
- Intermediate classes `AbstractButton`, `JTextComponent`

## Hierarchy of Geometrical Shapes

- First version of Java: few shapes, integer coordinates

      Point
      Rectangle
      Polygon

- Java 2: sophisticated shapes, floating-point coordinates

      Point2D
      Rectangle2D
      RoundRectangle2D
      Line2D
      Ellipse2D
      Arc2D
      QuadCurve2D
      CubicCurve2D
      GeneralPath
      Area

- All but `Point2D` implement `Shape` interface type

## Hierarchy of Geometrical Shapes

## Rectangular Shapes

- Subclasses of `RectangularShape`:

      Rectangle2D
      RoundRectangle2D
      Ellipse2D
      Arc2D

- `RectangularShape` has useful methods

      getCenterX/getCenterY
      getMinX/getMinY
      getMaxX/getMaxY
      getWidth/getHeight
      setFrameFromCenter/setFrameFromDiagonal

## Float/Double Classes

- Each class has two subclasses, e.g.

      Rectangle2D.Double
      Rectangle2D.Float

- Are also inner classes!
  (Just to avoid even longer class names)
- Implementations have `double`/`float` fields
- Most methods have `double` parameters/return values

## Float/Double Classes

    public class Rectangle2D
    {
       public static class Float extends Rectangle2D
       {
          public double getX() { return x; }
          public double getY() { return y; }
          public double getWidth() { return width; }
          public double getHeight() { return height;}
          public void setRect(float x, float y, float w, float h)
          {
             this.x = x; this.y = y;
             this.width = w; this.height = h;
          }
          public void setRect(double x, double y,
             double w, double h)
          {
             this.x = (float)x; this.y = (float)y;
             this.width = (float)w; this.height = (float)h;
          }
          ...
          public float x;
          public float y;
          public float width;
          public float height;
       }
       . . .

## Float/Double Classes

       . . .
       public static class Double extends Rectangle2D
          public double getX() { return x; }
          public double getY() { return y; }
          public double getWidth() { return width; }
          public double getHeight() { return height;}
          public void setRect(double x, double y,
             double w, double h)
          {
             this.x = x; this.y = y;
             this.width = w; this.height = h;
          }
          ...
          public double x;
          public double y;
          public double width;
          public double height;
       }
       ...
    }

## Float/Double Classes

- `Rectangle2D` class has no instance variables
- Template Method Pattern at work:

      public boolean contains(double x, double y)
      {
         double x0 = getX();
         double y0 = getY();
         return x >= x0 && y >= y0 &&
            x < x0 + getWidth() &&
            y < y0 + getHeight();
      }

- No need to use inner class after construction
  `Rectangle2D rect
  = new Rectangle2D.Double(5, 10, 20, 30);`

## TEMPLATE METHOD Pattern

Name in Design Pattern | Actual Name (Rectangles)
AbstractClass | Rectangle
ConcreteClass | Rectangle2D.Double
templateMethod() | contains
primitiveOpn() | getX, getY, getWidth, getHeight

## Hierarchy of Exception Classes

- Base of hierarchy: `Throwable`
- Two subclasses: `Error`, `Exception`
- Subclasses of `Error`: fatal
  (out of memory, assertion failure)
- Subclasses of `Exception:`

- Lots of checked exceptions
  (I/O, class not found)
- `RuntimeException`--its subclasses are unchecked
  (null pointer, index out of bounds)

## Hierarchy of Exception Classes

## Catching Exceptions

- Can have multiple `catch` clauses:

      try
      {
         code that may throw exceptions
      }
      catch (ExceptionType1 exception1)
      {
         handler for ExceptionType1
      }
      catch (ExceptionType2 exception1)
      {
         handler for ExceptionType2
      }
      . . .

- Can catch by superclass:
  `catch (IOException exception)
  ` catches `FileNotFoundException`

## Defining Exception Classes

- Decide exception should be checked
- Subclass `Exception` or `RuntimeException`
- Provide two constructors

      public class IllegalFormatException extends Exception
      {
         public IllegalFormatException() {}
         public IllegalFormatException(String reason)
         { super(reason); }
      }

- Throw exception when needed:
  `throw new` IllegalFormat `Exception("number expected");`

## When Not to Use Inheritance

- From a tutorial for a C++ compiler:

    public class Point
    {
       public Point(int anX, int aY) { ... }
       public void translate(int dx, int dy) { ... }
       private int x;
       private int y;
    }

    public class Circle extends Point // DON'T
    {
       public Circle(Point center, int radius) { ... }
       public void draw(Graphics g) { ... }
       private int radius;
    }

## When Not to Use Inheritance

- Huh? A circle isn't a point.
- By accident, inherited `translate` works for circles
- Same tutorial makes `Rectangle` a subclass of `Point`:

      public class Rectangle extends Point // DON'T
      {
         public Rectangle(Point corner1, Point corner2) { ... }
         public void draw(Graphics g) { ... }
         public void translate(int dx, int dy) { ... }
         private Point other;
      }

## When Not to Use Inheritance

- That's even weirder:

      public void translate(double dx, double dy)
      {
         super.translate(dx, dy);
         other.translate(dx, dy);
      }

- Why did they do that?
- Wanted to avoid abstract class `Shape`
- Remedy: Use aggregation.
- Circle, Rectangle classes have points

## When Not to Use Inheritance

- Java standard library:

      public class Stack extends Vector // DON'T
      {
         Object pop() { ... }
         void push(Object item) { ... }
         ...
      }

- Bad idea: Inherit all `Vector` methods
- Can insert/remove in the middle of the stack
- Remedy: Use aggregation

      public class Stack
      {
         ...
         private Vector elements;
      }