## Object-Oriented Design & Patterns

#### Cay S. Horstmann

### Chapter 4

### Interfaces and Polymorphism

## Chapter Topics

- Displaying an Image
- Polymorphism
- Drawing Shapes
- The Comparable Interface
- The Comparator Interface
- Anonymous Classes
- Frames and User Interface Components
- User Interface Actions
- Timers
- Designing an Interface

## Displaying an Image

- Use `JOptionPane` to display message:

      JOptionPane.showMessageDialog(null, "Hello, World!");

- Note icon to the left

## Displaying an Image

- Can specify arbitrary image file

      JOptionPane.showMessageDialog(
         null,
         "Hello, World!",
         "Message",
         JOptionPane.INFORMATION_MESSAGE,
         new ImageIcon("globe.gif"));

## Displaying an Image

- What if we don't want to generate an image file?
- Fortunately, can use any class that implements `Icon` interface type
- `ImageIcon` is one such class
- Easy to supply your own class

## The `Icon` Interface Type

    public interface Icon
    {
       int getIconWidth();
       int getIconHeight();
       void paintIcon(Component c, Graphics g, int x, int y)
    }

## Interface Types

- No implementation
- Implementing class must supply implementation of all methods
- Ch4/icon2/MarsIcon.java
- `showMessageDialog` expects `Icon` object
- Ok to pass `MarsIcon`
- Ch4/icon2/IconTest.java

## The Icon Interface Type and Implementing Classes

## Polymorphism

- public static void showMessageDialog(...Icon anIcon)
- showMessageDialog shows
  - icon
  - message
  - OK button
- showMessageDialog must compute size of dialog
- width = icon width + message size + blank size
- How do we know the icon width?

      int width = anIcon.getIconWidth();

## Polymorphism

- showMessageDialog doesn't know which icon is passed
  - ImageIcon?
  - MarsIcon?
  - . . .?
- The actual type of anIcon is not Icon
- There are no objects of type Icon
- anIcon belongs to a class that implements Icon
- That class defines a getIconWidth method

## A Variable of Interface Type

## Polymorphism

- Which `getIconWidth` method is called?
- Could be
  - MarsIcon.getIconWidth
  - ImageIcon.getIconWidth
  - . . .
- Depends on object to which `anIcon` reference points, e.g.

      showMessageDialog(..., new MarsIcon(50))

- Polymorphism: Select different methods according to actual object type

## Benefits of Polymorphism

- Loose coupling

- showMessageDialog decoupled from ImageIcon
- Doesn't need to know about image processing

- Extensibility

- Client can supply new icon types

## Drawing Shapes

- `paintIcon` method receives graphics context of type `Graphics`
- Actually a `Graphics2D` object in modern Java versions

      public void paintIcon(Component c, Graphics g, int x, int y)
      {
         Graphics2D g2 = (Graphics2D)g;
         . . .
      }

- Can draw any object that implements `Shape` interface

      Shape s = . . .;
      g2.draw(s);

## Drawing Rectangles and Ellipses

- `Rectangle2D.Double` constructed with

- top left corner
- width
- height

- g2.draw(new Rectangle2D.Double(x, y, width, height));

- For `Ellipse2D.Double`, specify bounding box

## Drawing Ellipses

## Drawing Line Segments

- `Point2D.Double` is a point in the plane
- `Line2D.Double` joins to points

      Point2D.Double start = new Point2D.Double(x1, y1);
      Point2D.Double end = new Point2D.Double(x2, y2);
      Shape segment = new Line2D.Double(start, end);
      g2.draw(segment);

## Relationship Between Shape Classes

## Drawing Text

- g2.drawString(text, x, y);
- x, y are base point coordinates

## Filling Shapes

- Fill interior of shape

      g2.fill(shape);

- Set color for fills or strokes:
  `g2.setColor(Color.red);`

- Program that draws car
  Ch4/icon3/CarIcon.java

## The `Comparable` Interface Type

- `Collections` has static `sort` method:

      ArrayList a = . . .
      Collections.sort(a);

- Objects in list must implement the `Comparable` interface type

      public interface Comparable
      {
         int compareTo(Object other);
      }

- `object1.compareTo(object2)` returns

- Negative number if `object1` less than `object2`
- 0 if objects identical
- Positive number if `object1` greater than `object2`

## The `Comparable` Interface Type

- `sort` method compares and rearranges elements
  `if (object1.compareTo(object2) > 0) . . .`
- `String` class implements `Comparable` interface type: lexicographic (dictionary) order
- `Country` class: compare countries by area
  Ch4/sort1/Country.java
  Ch4/sort1/CountrySortTest.java

## The `Comparator` interface type

- How can we sort countries by name?
- Can't implement `Comparable` twice!
- `Comparator` interface type gives added flexibility

      public interface Comparator
      {
         int compare(Object object1, Object object2);
      }

- Pass comparator object to `sort`:

      Collections.sort(list, comp);

## The `Comparator` interface type

- Ch4/sort2/CountryComparatorByName.java
  Ch4/sort2/ComparatorTest.java
- Comparator object is a function object
- This particular comparator object has no state
- State can be useful, e.g. flag to sort in ascending or descending order

## Anonymous Classes

- No need to name objects that are used only once

      Collections.sort(countries,
         new CountryComparatorByName());

- No need to name classes that are used only once

      Comparator comp = new
         Comparator()
         {
            public int compare(Object obj1, Object obj2)
            {
               Country country1 = (Country)obj1;
               Country country2 = (Country)obj2;
               return country1.getName().compareTo(country2.getName());
            }
         };

## Anonymous Classes

- anonymous new expression:

- defines anonymous class that implements `Comparator`
- defines `compare` method of that class
- constructs one object of that class

- Cryptic syntax for very useful feature

## Anonymous Classes

- Commonly used in factory methods:
  public static Comparator comparatorByName()
  {
  return new Comparator()
  {
  public int compare(Object o1, Object o2) { . . . }
  };
  }
- Collections.sort(a, Country.comparatorByName());
- Neat arrangement if multiple comparators make sense
  (by name, by area, ...)

## Frames

- Frame window has decorations

- title bar
- close box
- provided by windowing system

-     JFrame frame = new JFrame();
      frame.pack();
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.show();

## Adding Components

- Construct components

      JButton helloButton = new JButton("Say Hello");

- Set content pane layout

      Container contentPane = frame.getContentPane();
      container.setLayout(new FlowLayout());

- Add components to content pane

      contentPane.add(helloButton);

- Ch4/frame/FrameTest.java

## User Interface Actions

- Previous program's buttons don't have any effect
- Add listener object(s) to button
- Belong to class implementing `ActionListener` interface type

      public interface ActionListener
      {
         int actionPerformed(ActionEvent event);
      }

- Listeners are notified when button is clicked

## User Interface Actions

- Add action code into actionPerformed method
- Gloss over routine code

    helloButton.addActionListener(new
       ActionListener()
       {
          public void actionPerformed(ActionEvent event)
          {
              textField.setText("Hello, World");
          }
       });

- When button is clicked, text field is set

## Accessing Variables from Enclosing Scope

- Remarkable: Inner class can access variables from enclosing scope
  e.g. textField
- Can access enclosing instance fields, local variables
- Local variables must be marked `final
  final JTextField textField = ...;
  `

## User Interface Actions

- Constructor attaches listener:

      helloButton.addActionListener(listener);

- Button remembers all listeners
- When button clicked, button notifies listeners

      listener.actionPerformed(event);

- Listener sets text of text field

      textField.setText("Hello, World!");

- Ch4/action1/ActionTest.java

## Constructing Related Actions

- Write helper method that constructs objects
- Pass variable information as parameters
- Declare parameters final

    public static ActionListener createGreetingButtonListener(
       final String message)
    {
       return new
          ActionListener()
          {
             public void actionPerformed(ActionEvent event)
             {
                textField.setText(message);
             }
          };
    }

## Timers

- Supply delay, action listener
  ActionListener listener = ...;
  final int DELAY = 1000; // 1000 millisec = 1 sec
  Timer t = new Timer(DELAY, listener);
  t.start();
- Action listener called when delay elapsed
- Ch4/timer/TimerTest.java

## Defining a New Interface Type

- Use timer to move car shapes
- Draw car with CarShape
- Two responsibilities:

- Draw shape
- Move shape

- Define new interface type MoveableShape

## CRC Card for the MoveableShape Interface Type

## Defining a New Interface Type

- Name the methods to conform to standard library
- public interface MoveableShape
  {
  void draw(Graphics2D g2);
  void translate(int dx, int dy);
  }
- CarShape class implements MoveableShape
  public class CarShape implements MoveableShape
  {
  public void translate(int dx, int dy)
  { x += dx; y += dy; }
  . . .
  }

## Implementing the Animation

- Label contains icon that draws shape
- Timer action moves shape, calls repaint on label
- Label needs Icon, we have MoveableShape
- Supply ShapeIcon adapter class
- ShapeIcon.paintIcon calls MoveableShape.draw

## Implementing the Animation

- Ch4/animation/MoveableShape.java
- Ch4/animation/ShapeIcon.java
- Ch4/animation/AnimationTest.java
- Ch4/animation/CarShape.java

## Implementing the Animation