Inheritance • Inheritance – reminder from dIntProg – pre- postconditions • Graphics programming with inheritance Inheritance – extending JComponent – Mouse(Motion)Adapters – Abstract classes and TEMPLATE pattern – Refactoring Horstmann ch. 6.1.7-6.6, 6.9 • Class hierarchies – Swing – Geometric shapes – Exceptions • When not to use inheritance Inheritance Inheritance Hierarchy • concepts (from dIntProg) Manager is subclass of Employee – subclass specializes super class ... extends ... – inheritance hierarchies (though manager is superior to most employees) – overriding method – invoke super class method: super.methodname() – invoke super class constructor: super(...) – substitution principle • overridden methods and pre/postconditions – preconditions of redefined method at most as strong – postconditions of redefined method at least strong The Substitution Principle Preconditions • Precondition of redefined method at most as strong • Formulated by Barbara Liskov • public class Employee { /** • You can use a subclass object whenever a Sets the employee salary to a given value. superclass object is expected @param aSalary the new salary @precondition aSalary > 0 • Example: */ public void setSalary(double aSalary) { ... } Employee e; } ... • Can we redefine Manager.setSalary with precondition salary > 100000 ? System.out.println("salary=" + e.getSalary()); • No--Could be defeated: • Can set e to Manager reference Manager m = new Manager(); Employee e = m; • Polymorphism: Correct getSalary method is e.setSalary(50000); invoked
Postconditions, Visibility, Graphic Programming with Exceptions Inheritance • Graphics by inheritance • Postcondition of redefined method at least as strong – extend JComponent – override paintComponent • Example: Employee.setSalary promises not to • Mouse(Motion)Listeners decrease salary – extend an adapter class • Then Manager.setSalary must fulfill postcondition – example: drag a car shape • Abstract classes and Template pattern • Redefined method cannot be more private. – Example: Scene editor with selectable shape (Common error: omit public when redefining) – abstact class for selectable shape behavior • Redefined method cannot throw more checked – template pattern for drawing selected shape exceptions – methods with protected access Graphic Programming with Overriding paintComponent Inheritance • Chapter 4: Create drawings by implementing • Draw a car: Icon interface type public class CarComponent extends • Now: Form subclass of JComponent JComponent { public class MyComponent extends public void paintComponent(Graphics g) { JComponent { Graphics2D g2 = (Graphics2D)g; public void paintComponent(Graphics g) { drawing instructions go here car.draw(g2); } } ... ... } private CarShape car; • Advantage: Inherit behavior from JComponent } • Example: Can attach mouse listener to JComponent Mouse Listeners Mouse Adapters • What if you just want to listen to mousePressed ? • Attach mouse listener to component • Extend MouseAdapter • Can listen to mouse events (clicks) or mouse motion events public interface MouseListener { public class MouseAdapter implements MouseListener { void mouseClicked(MouseEvent event); public void mouseClicked(MouseEvent event) {} void mousePressed(MouseEvent event); public void mousePressed(MouseEvent event) {} void mouseReleased(MouseEvent event); public void mouseReleased(MouseEvent event) {} void mouseEntered(MouseEvent event); public void mouseEntered(MouseEvent event) {} void mouseExited(MouseEvent event); public void mouseExited(MouseEvent event) {} } } public interface MouseMotionListener { • Component constructor adds listener: void mouseMoved(MouseEvent event); void mouseDragged(MouseEvent event); addMouseListener(new } MouseAdapter() { public void mousePressed(MouseEvent event) { mouse action goes here } } );
• mousePressed remembers point of mouse press Car Mover Program addMouseListener(new MouseAdapter() { public void mousePressed (MouseEvent event) { • Use the mouse to drag a car shape mousePoint = event.getPoint(); if (!car.contains(mousePoint)) mousePoint = null; } • Car panel has mouse + mouse motion listeners }); • mouseDragged translates car shape addMouseMotionListener(new MouseMotionAdapter() { public void mouseDragged (MouseEvent event) { Car if (mousePoint == null) return; Component Point lastMousePoint = mousePoint; mousePoint = event.getPoint(); double dx = mousePoint.getX() - lastMousePoint.getX(); double dy = mousePoint.getY() - lastMousePoint.getY(); car.translate( (int) dx, (int) dy ); repaint(); } }); JComponent Scene Editor The SceneShape Interface Type • keep track of selection state • Draws various shapes • draw plain or selected shape • User can add, delete, • move shape move shapes • hit testing : is a point (e.g. mouse position) inside? • User selects shape with mouse • public interface SceneShape { void setSelected(boolean b); • Selected shape is boolean isSelected(); void draw(Graphics2D g2); highlighted (filled in) void drawSelection(Graphics2D g2); void translate(int dx, int dy); boolean contains(Point2D aPoint); } CarShape and HouseShape Abstract Classes Classes public class CarShape implements SceneShape { • Factor out common behavior ( setSelected, isSelected ) ... public void setSelected(boolean b) { selected = b; } • Subclasses inherit common behavior public boolean isSelected() { return selected; } • Some methods still undefined private boolean selected; ( draw, drawSelection, translate, contains ) } public abstract class SelectableShape public class HouseShape implements SceneShape { implements SceneShape { ... public void setSelected(boolean b) { selected = b; } public void setSelected(boolean b) { selected = b; } public boolean isSelected() { return selected; } public boolean isSelected() { return selected; } private boolean 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 Scene Editor Types • Mouse listener selects/unselects item • Abstract classes can have fields addMouseListener(new MouseAdapter() { • Interface types can only have constants public void mousePressed (MouseEvent event) { ( public static final ) mousePoint = event.getPoint(); for (SceneShape s : shapes) { • Abstract classes can define methods if (s.contains(mousePoint)) s.setSelected(!s.isSelected()); • Interface types can only declare methods } • A class can implement any number of repaint(); } interface types } ); • In Java, a class can extend only one other class Scene Editor Scene Editor • Mouse motion listener drags selected items • Remove button removes selected items addMouseMotionListener(new MouseMotionAdapter() { public void mouseDragged (MouseEvent event) { removeButton.addActionListener(new Point lastMousePoint = mousePoint; mousePoint = event.getPoint(); ActionListener() { for (SceneShape s : shapes) public void actionPerformed (ActionEvent event) { if (s.isSelected()) { double dx = mousePoint.getX() - lastMousePoint.getX(); scene.removeSelected(); double dy = mousePoint.getY() - lastMousePoint.getY(); } s.translate((int)dx,(int)dy); } } repaint(); ); } } );
Uniform Highlighting Technique 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) } Template Method TEMPLATE METHOD Pattern Context • drawSelection calls draw • An algorithm is applicable for multiple types. • Must declare draw in SelectableShape • The algorithm can be broken down into primitive operations . The • No implementation at that level! primitive operations can be different for each type • Declare as abstract method • The order of the primitive operations doesn't depend on the type public abstract void draw(Graphics2D g2); Solution • Defined in CarShape , HouseShape • Define a superclass that has a method for the algorithm and abstract • drawSelection method calls draw, translate methods for the primitive operations. • drawSelection doesn't know which methods -- • Implement the algorithm to call the primitive operations in the appropriate order. polymorphism • Do not define the primitive operations in the superclass, or define • drawSelection is a template method them to have appropriate default behavior. • Each subclass defines the primitive operations but not the algorithm. TEMPLATE METHOD Pattern TEMPLATE METHOD Pattern Name in Design Pattern Actual Name (selectable shapes) AbstractClass SelectableShape ConcreteClass CarShape, HouseShape templeteMethod() drawSelection translate, draw primitiveOp1(), primitiveOp2()
More recommend