450 likes | 543 Views
Big Java. Chapters 9-10. Interfaces for Code Reuse. Interface specifies common set of operations All methods are abstract (like prototypes), no implementation. Must be public. Interface may have constants, but no instance fields (never instantiate an interface directly)
E N D
Big Java Chapters 9-10
Interfaces for Code Reuse • Interface specifies common set of operations • All methods are abstract (like prototypes), no implementation. Must be public. • Interface may have constants, but no instance fields (never instantiate an interface directly) • Other classes can then implement that interface
public interface Measureable { double getMeasure(); } public class BankAccount implements Measurable { public double getMeasure() { return balance; } . . . } Interface Example public class Coin implements Measurable { public double getMeasure() { return value; } . . . } keyword public required, default is package Can implement more than one interface!
Interface Example, continued public class DataSet { public void add(Measurable x) { sum = sum + x.getMeasure(); if (count == 0 || max.getMeasure() < x.getMeasure()) max = x; count++; } public Measureable getMaximum() { return max; } private double sum; private Measurable max; private int count; }
Interface Example, continued BankAccount account = new BankAccount(1000); Measurable x = account; // OK to convert Coin dime = new Coin(0.1, “dime”); x = dime; // Also OK – notice we don’t know type of // x, just that it implements Measurable, so it is // OK to call getMeasure. May do cast if you are // sure of the type DataSet coinData = new DataSet(); coinData.add(new Coin(0.25, “quarter”); Measurable max = coinData.getMaximum(); String coinName = max.getName(); // Error Coin maxCoin = (Coin) max; // Error if you’re wrong! String coinName = max.getName(); Measurable x = new Rectangle(5, 10, 20, 20); //not OK
Polymorphism • How is correct method executed? Measurable x = new BankAccount(1000); double m = x.getMeasure(); x = new Coin(0.1, “dime”); m = x.getMeasure(); JVM locates correct method. What did we do in C++? Overloading method – early binding (e.g., default vs 1-parameter constructor; static) Polymorphism – late binding (dynamic)
UML Diagram Coin BankAccount is-a (triangular tip) stereotype indicator <<interface>> Measurable DataSet uses (open arrow tip)
Design Idea: Callbacks Limitations to Measurable Interface: • Can only add Measurable interface to classes under your control (so can only have DataSet of those classes… e.g., no DataSet of Rectangles) • You can only measure an object in one way, because only one getMeasure function. What if you need two measures? (e.g., by balance and interest rate, for a savings account)
Callbacks (continued) • Instead of Measurable, add Measurer interface • Method measure takes an Object (parent of all other classes) and returns that object’s “measure” • The “callback” is the method “measure” which DataSet can call when it needs information • The implementation of measure will vary based on the underlying data type
Callback DataSet Example public interface Measurer { double measure(Object anObject; } public class DataSet { public void add(Object x) { sum += measurer.measure(x); if (count == 0 || measurer.measure(max) < measurer.measure(x)) max = x; count++; } }
CallBack DataSet (continued) public class RectangleMeasurer implements Measurer { public double measure(Object anObject) { Rectangle aRect = (Rectangle) anObject); double area = aRect.getWidth() * aRect.getHeight(); return area; } } Measurer m = new RectangleMeasurer(); DataSet data = new DataSet(m); data.add(new Rectangle(5, 10, 20, 20)); . . .
UML Diagram Rectangle Rectangle Measurer is-a (triangular tip) <<interface>> Measurer DataSet uses (open arrow tip)
Reading Assignment • Read the Wikipedia entry for Callback Functions
Inner Classes • A trivial class that is only needed to provide functionality to the enclosing (outer) class • C++ has nested classes, but Java provides access to enclosing class variables, which is convenient class OuterClassName { method signature { . . . class InnerClassName { methods fields } } } class OuterClassName { methods fields access class InnerClassName { methods fields } } creates class files with $ in names
More GUI Programming • GUIs are under control of the user, not the program • Java programs react to a wide variety of user interface events – button pushes, mouse clicks, window manipulation, etc. • Program installs event listeners for events of interest • Need to know the event source– e.g., button, text box, window etc. • All listeners implement the particular interface for that type of event (e.g., button listeners must implement ActionListener)
import java.awt.event.ActionEvent; import java.awt.event.ActionListener; /** An action listener that prints a message. */ public class ClickListener implements ActionListener { public void actionPerformed(ActionEvent event) { System.out.println("I was clicked."); } } Simple Button Example method signature must be exact!
Simple Button Example (continued) import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JFrame; /** This program demonstrates how to install an action listener. */ public class ButtonViewer { public static void main(String[] args) { JFrame frame = new JFrame(); JButton button = new JButton("Click me!"); frame.add(button); ActionListener listener = new ClickListener(); button.addActionListener(listener); frame.setSize(FRAME_WIDTH, FRAME_HEIGHT); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } private static final int FRAME_WIDTH = 100; private static final int FRAME_HEIGHT = 60; }
Inner Classes as Button Listeners import java.awt.event.*; import javax.swing.*; public class InvestmentViewer1 { public static void main(String[] args) { JFrame frame = new JFrame(); JButton button = new JButton("Add Interest"); frame.add(button); // The application adds interest to this bank account final BankAccount account = new BankAccount(INITIAL_BALANCE); class AddInterestListener implements ActionListener { public void actionPerformed(ActionEvent event) { // The listener accesses variable from surrounding block double interest = account.getBalance()*INT_RATE / 100; account.deposit(interest); System.out.println("balance: " + account.getBalance()); } } ActionListener listener = new AddInterestListener(); button.addActionListener(listener); . . .normal frame code here } … constants defined here }
More GUI Classes and Details • JPanel – container used to organize your program layout • JLabel – provides a text description • frame.getContentPane().add(aComponent) is the same as frame.add(aComponent) – getContentPane was needed in earlier versions of Java • Don’t use a container as a listener • may have more than one button etc. • separates button definition from button action
On Your Own • Read 9.9 Processing Timer Events and 9.10 Mouse Events
On to Chapter 10… Inheritance
Inheritance Basics • Models “is-a” relationship, same as C++ • requires extends keyword • All classes are children of class Object • Object has several methods that are frequently overridden: • toString: returns a string that describes the state of the object, automatically called by System.out.println(objectRef); • clone: creates a deep copy of an object • equals: does a field-by-field comparison, returns boolean result
Simple Inheritance Example class SavingsAccount extends BankAccount { public SavingsAccount(double balance, double rate) { super(balance); // calls parent constructor interestRate = rate; } void addInterest() { // use getters/setters unless protected double interest = getBalance() * interestRate / 100; deposit(interest); } private double interestRate; }
UML for Inheritance Object should be “hollow triangle” tip BankAccount SavingsAccount
Can have Inheritance Hierarchy JComponent JTextComponent JPane JLabel AbstractButton JToggleButton JButton JTextField JTextArea JRadioButton JCheckBox
More on Inheritance SavingsAccount collegeFund = new SavingsAccount(1000, 0.1); BankAccount anAccount = collegeFund; Object anObject = collegeFund; collegeFund.addInterest; // OK anAccount.addInterest; //not OK String aString = anObject.toString(); • OK – but what will it contain?
Typecasts • If you know that a reference contains a specific type of object, you can perform a cast (will be an exception if you’re wrong) BankAccount myAccount = (BankAccount) anObject; • Can use instanceof to test class type if (anObject instanceof BankAccount) { BankAccount myAccount = (BankAccount) anObject; … }
Polymorphism • In Java, method calls are always determined by the type of the actual object, not the type of the object reference (unlike C++, where virtual keyword is needed)
Abstract Classes • Concept same as C++, use in same types of situations (i.e., force subclasses to define behavior • Requires use of abstract keyword • As in C++, you can’t initialize objects of an abstract type public abstract class BankAccount { public abstract void deductFees(); . . .} BankAccount anAccount; anAccount = new BankAccount(); // ERROR anAccount = new SavingsAccount(); // OK (deductFees defined)
Final Methods and Classes • May occasionally want to prevent others from creating subclasses or overriding methods public final class String { . . . } public final boolean checkPassword(String password) { . . . }
Access control • public – like C++, good for constants • private – like C++, good for instance fields • protected – like C++ but extends to package, convenient for inheritance • package • all methods of classes in the same package have access • this is the default! (easy to forget) • OK if several classes in package collaborate, but generally inner classes are better, packages are not secure (anyone can add a class to the package) public class BankAccount { double balance; // package access . . . }
Object Method Examples – toString class object describes class & properties public class BankAccount { public String toString() { return getClass().getName() + balance; } . . . } public class SavingsAccount { public String toString() { return super.toString + “ Rate” + interestRate; } . . . } call to parent class
Object Method Examples – equals public boolean equals(Object otherObject) { if (otherObject == null) return false; if (getClass() != otherObject.getClass()) return false; BankAccount account = (BankAccount) otherObject; return balance == account.balance; // should call super.equals first if you write an // equals for a subclass // instanceof sometimes used, but it would return // true for a subclass } What happens if you don’t override equals?
Quality Tip 10.1 Clone mutable instance fields in accessor methods public class Customer { public Customer(String aName) { name = aName; account = new BankAccount(); } public String getName() { return name; } public BankAccount getAccount() return account } private String name; private BankAccount account; } Customer harry = new Customer(“Harry”); BankAccount acct = harry.getAccount(); account.withdraw(10000);
Object Method Examples – clones • Read advanced topic 10.6 if you need to write a clone method
GUIs with Inheritance and TextField import java.awt.event.*; import javax.swing.*; public class InvestmentFrame extends JFrame { public InvestmentFrame() { account = new BankAccount(INITIAL_BALANCE); resultArea = new JTextArea(AREA_ROWS, AREA_COLUMNS); resultArea.setEditable(false); // Use helper methods createTextField(); createButton(); createPanel(); setSize(FRAME_WIDTH, FRAME_HEIGHT); }
GUIs with Inheritance and TextField private void createTextField() { rateLabel = new JLabel("Interest Rate: "); final int FIELD_WIDTH = 10; rateField = new JTextField(FIELD_WIDTH); rateField.setText("" + DEFAULT_RATE); }
GUIs with Inheritance and TextField private void createButton() { button = new JButton("Add Interest"); class AddInterestListener implements ActionListener { public void actionPerformed(ActionEvent event) { double rate = Double.parseDouble( rateField.getText()); double interest = account.getBalance() * rate / 100; account.deposit(interest); resultArea.append(account.getBalance() + "\n"); } } ActionListener listener = new AddInterestListener(); button.addActionListener(listener); }
GUIs with Inheritance and TextField private void createPanel() { panel = new JPanel(); panel.add(rateLabel); panel.add(rateField); panel.add(button); JScrollPane scrollPane = new JScrollPane(resultArea); panel.add(scrollPane); add(panel); }
GUIs with Inheritance and TextField private JLabel rateLabel; private JTextField rateField; private JButton button; private JTextArea resultArea; private JPanel panel; private BankAccount account; private static final int FRAME_WIDTH = 400; private static final int FRAME_HEIGHT = 250; private static final int AREA_ROWS = 10; private static final int AREA_COLUMNS = 30; private static final double DEFAULT_RATE = 5; private static final double INITIAL_BALANCE = 1000; }
GUIs with Inheritance and TextField import javax.swing.JFrame; /** This program displays the growth of an investment. */ public class InvestmentViewer4 { public static void main(String[] args) { JFrame frame = new InvestmentFrame(); frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } }
Exercise • Design and implement a GUI for an application that includes: • An ArrayList of BankAccount objects • Actual objects may be either SavingsAccount or CheckingAccount • User should be able to create new accounts or maintain existing accounts (withdraw/deposit etc.) • Add extra methods/fields to BankAccount classes as you see fit