Abstraction, Inheritance, and Polymorphism in the Dance Studio in Java Maria Litvin Phillips Academy, Andover, MA mlitvin@andover.edu Why is The College Board using Java? Java: Three reasons: • OOP • OOP • OOP The Recommendations of the AP Computer Science Ad Hoc Committee: “Object Orientation involving encapsulation, inheritance, polymorphism, and abstraction, is an important approach in programming and program design. It is widely accepted and used in industry and is growing in popularity in the first and second college-level programming courses.” Some other reasons to move on to Java: • • • • • • • • • • Internet applets Platform-independent software Relatively easy graphics and GUI programming Lots of library packages Free compiler and IDEs Colleges are teaching it Companies are using it Students want it (Teachers welcome it... ;) (Programmers drink it... :) What are OOP’s claims to fame? • Better suited for team development • Facilitates utilizing and creating reusable software components • Easier GUI programming • Easier program maintenance OOP in a Nutshell: • A program models a • Each object belongs to a world of interacting class; a class defines objects properties of its objects • Objects create other • A class implements an objects and “send ADT; the data type of an messages” to each other object is its class (in Java, call each • Programmers write classes other’s methods) (and reuse existing classes) Java != C++ • It may be tempting to teach only conventional (procedural) programming in Java class MyMath { public static long factorial(int n) { long f = 1; int i; for (i = 2; i <= n; i++) f *= i; return f; } public static void main(String[] args) { System.out.println("10! = " + factorial(10)); } • It would mean to miss the point } OOP Case Study: Dance Studio Exercise 1: Run the Dance Studio applet. Exercise 2: Set up a project in an IDE (e.g. BlueJ) for the Dance Studio applet. Compile and run. Quiz: How many classes were written for this applet? A. 1 B. 2 C. 5 D. 10 E. 17 Controller DanceStudio Music DanceModel View Model Dancer DanceFloor MaleDancer FemaleDancer Foot MaleFoot FemaleFoot Good news: The classes are fairly short DanceStudio 92 lines MaleDancer 10 lines DanceModel 50 lines FemaleDancer 10 lines DanceFloor 30 lines Foot 100 lines Music 52 lines MaleFoot 42 lines Dancer 80 lines FemaleFoot 42 lines • In OOP, the number of classes is not considered a problem Quiz: How many Java/Swing library classes are used, explicitly or implicitly, in this applet? A. 4 B. 8 C. 12 D. 20-50 E. 100-500 Answer: E (hundreds) /* * @(#)JButton.java 1.83 00/03/14 * Copyright 1997-2000 Sun Microsystems, Inc. * All Rights Reserved. * ... */ package javax.swing; import java.util.EventListener; import java.awt.*; import java.awt.event.*; import java.awt.image.*; import javax.swing.plaf.*; import javax.swing.event.*; import javax.accessibility.*; import java.io.ObjectOutputStream; import java.io.ObjectInputStream; import java.io.IOException; ... Abstraction Abstraction means ignoring irrelevant features, properties, or functions and emphasizing the relevant ones... “Relevant” to what? ... relevant to the given project (with an eye to future reuse in similar projects). Abstraction Dancer MaleDancer FemaleDancer public abstract class Dancer { // Fields (data members): protected Foot leftFoot; protected Foot rightFoot; private String mySteps[]; private int stepIndex = -1; public void setSteps(String steps[]) { mySteps = steps; stepIndex= -1; } Continued Dancer (cont’d...) // Methods (member functions): public void nextStep() { ... } public void makeStep(String sideStr, String weightStr, String dirStr) // e.g. makeStep("left", "weightboth", "F"); { ... } public void draw(Graphics g) { leftFoot.draw(g); rightFoot.draw(g); } Continued Dancer (cont’d...) // // // // Private Methods (callable only from constructors and methods of this class, i.e. "private" to the programmer who wrote this class) private String[] parseNextStep() { ... } } How is Dancer used in Dance Studio? public class DanceModel { ... private Dancer dancers[]; public DanceModel(DanceFloor floor, int floorDir, String steps1[], String[] steps2) { ... dancers = new Dancer[2]; dancers[0] = new MaleDancer(x1, y1, dir1); dancers[0].setSteps(steps1); dancers[1] = new FemaleDancer(x2, y2, dir2); dancers[1].setSteps(steps2); ... } Continued DanceModel (cont’d...) public void nextBeat() { for (int k = 0; k < dancers.length; k++) dancers[k].nextStep(); ... } DanceStudio Music DanceModel Dancer DanceFloor MaleDancer FemaleDancer Foot MaleFoot FemaleFoot Exercise 3: In the Dance Studio applet, change the DanceModel class to place four dancers (two couples) on the dance floor, as shown: Hint: • In DanceModel, add a MaleDancer and a FemaleDancer as follows: Dancer’s position (in pixels) x y Dancer’s orientation 0 6 2 4 dancer[...] = new MaleDancer(x, y, dir); Exercise 4: (a) (b) Compile and run the Banner applet Modify Walker.java so that instead of a flying banner, a “man” or a “woman” walks across. Hint: • Use MaleDancer or FemaleDancer— they can “walk” too... MaleDancer walker = new MaleDancer(x, y, dir); • Make him/her take one step with one foot, then two steps with the other foot, etc. To make a step: "left" or "right" walker.makeStep(side, "weightboth", "F"); Encapsulation Encapsulation means that all data members (fields) of a class are declared private. Some methods may be private, too. The class interacts with other classes (called the clients of this class) only through the class’s constructors and public methods. Constructors and public methods of a class serve as the interface to class’s clients. Encapsulation Foot MaleFoot FemaleFoot public abstract class Foot { private static final int footWidth = 24; private private private private boolean amLeft; int myX, myY; int myDir; boolean myWeight; All fields are private // Constructor: protected Foot(String side, int x, int y, int dir) { amLeft = side.equals("left"); myX = x; myY = y; myDir = dir; myWeight = true; } Continued Foot (cont’d...) // Public methods -- accessors: public static int getWidth() { return footWidth; } public boolean isLeft() { return amLeft; } Continued Foot (cont’d...) public int getX() { return myX; } public int getY() { return myY; } public int getDir() { return myDir; } public boolean hasWeight() { return myWeight; } Continued Foot (cont’d...) // Public methods -- modifiers: public void setWeight(boolean weight) { myWeight = weight; } public void move(int dx, int dy) { ... } public void turn(int dir) { // dir > 0 -- clockwise; dir < 0 -- counterclockwise myDir = (8 + myDir + dir) % 8; } Continued Foot (cont’d...) // Public methods -- drawing: public void draw(Graphics g) { ... if (isLeft()) drawLeft(g); else drawRight(g); ... } // Public methods -- abstract: public abstract void drawLeft(Graphics g); public abstract void drawRight(Graphics g); } Encapsulation ensures that structural changes remain local • Changes in the code create software maintenance problems • Usually, the structure of a class (as defined by its fields) changes more often than the class’s constructors and methods • Encapsulation ensures that when fields change, no changes are needed in other classes (a principle known as “locality”) Encapsulation (cont’d) Example: Suppose in Foot we decided to use private String mySide; instead of private boolean amLeft; Before: After: public abstract class Foot { ... private boolean amleft; ... // Constructor: protected Foot(String side, int x, int y, int dir) { amLeft = side.equals("left"); ... } public boolean isLeft() { return amLeft; } ... public abstract class Foot { ... private String mySide; ... // Constructor: protected Foot(String side, int x, int y, int dir) { mySide = side; ... } public boolean isLeft() { return side.equals("left"); } ... True or False? Abstraction and encapsulation are helpful for the following: Team development ________ Reusable software ________ GUI programming ________ Easier program maintenance ________ Answer: T Team development ________ T Reusable software ________ F GUI programming ________ Easier (True if you are working on system packages, such as Swing) T program maintenance ________ Inheritance A class can extend another class, inheriting all its data members and methods while redefining some of them and/or adding its own. Inheritance represents the is a relationship between data types. For example: a FemaleDancer is a Dancer. Inheritance Terminology: subclass or derived class superclass extends or base class public class FemaleDancer extends Dancer { ... } Inheritance (cont’d) Example: Dancer MaleDancer FemaleDancer Inheritance (cont’d) Constructors are not inherited. The FemaleDancer class only adds a constructor: public class FemaleDancer extends Dancer { public FemaleDancer(String steps[], int x, int y, int dir) { leftFoot = new FemaleFoot("left", x, y, dir); rightFoot = new FemaleFoot("right", x, y, dir); leftFoot.move(-Foot.getWidth() / 2, 0); rightFoot.move(Foot.getWidth() / 2, 0); } } Inheritance (cont’d) Example: Foot MaleFoot FemaleFoot public class FemaleFoot extends Foot { public FemaleFoot(String side, int x, int y, int dir) { super(side, x, y, dir); // calls Foot's constructor } // public void drawLeft(Graphics g) { ... } public void drawRight(Graphics g) { ... } } Supplies methods that are abstract in Foot: Inheritance may be used to define a hierarchy of classes in an application: Object Foot MaleFoot MaleLeftFoot MaleRightFoot FemaleFoot FemaleLeftFoot FemaleRightFoot Inheritance is also used to extend library classes (or someone else’s classes) public class DanceFloor extends JPanel { private DanceModel currentDance; public void updateDance(DanceModel dance) { ... } ... public void paintComponent(Graphics g) { ... } } Added field Added method Redefined method All methods of the base library class are available in your derived class • You don’t need to have the source code of a class to extend it (e.g., we don’t need to have JPanel.java to write your DanceFloor class that extends JPanel) Example: ... DanceFloor extends JPanel public class DanceStudio extends JApplet implements ActionListener { public void init() { ... floorPanel = new DanceFloor(); floorPanel.setBackground(Color.white); ... } ... The setBackground method is inherited from the Swing class JPanel (along with its 287 other methods) True or False? Inheritance is helpful for the following: Team development ________ Reusable software ________ GUI programming ________ Easier program maintenance ________ Answer: F Team development ________ T Reusable software ________ T GUI programming ________ ??? Easier program maintenance ________ Polymorphism Polymorphism ensures that the appropriate method is called for an object of a specific type when the object is disguised as a more general type. Good news: polymorphism is already supported in Java — all you have to do is use it properly. Polymorphism (cont’d) Situation 1: A collection (array, list, etc.) contains objects of different but related types, all derived from the same common base class. Example: public class DanceModel { ... public DanceModel(...) { dancers = new Dancer[2]; dancers[0] = new MaleDancer(...); dancers[1] = new FemaleDancer(...); ... } ... } Example (cont’d): public class DanceFloor extends JPanel { ... public void paintComponent(Graphics g) { ... Dancer dancer; for (int k = 0; (dancer = currentDance.getDancer(k)) != null; k++) dancer.draw(g); } } Polymorphism (cont’d) Situation 2: Abstract class’s fields are instantiated in concrete subclasses. Example: public abstract class Dancer { protected Foot leftFoot; protected Foot rightFoot; ... public void draw(Graphics g) { leftFoot.draw(g); rightFoot.draw(g); } } What kind of feet, male or female? This is unknown at compile time The correct “draw” will be called for the male or female feet, depending on the particular dancer Example (cont’d): public class FemaleDancer extends Dancer { public FemaleDancer(int x, int y, int dir) { leftFoot = new FemaleFoot("left", x, y, dir); rightFoot = new FemaleFoot("right", x, y, dir); ... } } Polymorphism replaces old-fashioned use of explicit object attributes and if-else (or switch) statements, as in: public abstract class Foot { ... public void draw(Graphics g) { ... if (isLeft()) drawLeft(g); else drawRight(g); ... } } Java: