Chapter 10

<< Chapter 9 | HomeworkTrailIndex | Chapter 11 >>

Inheritance

Demo1:Accounts

BankAccount.java

/**
   A bank account has a balance that can be changed by 
   deposits and withdrawals.
*/
public class BankAccount
{  
    private double balance; 
  /**
      Constructs a bank account with a zero balance.
   */
   public BankAccount()
   {  
      balance = 0;
   }

   /**
      Constructs a bank account with a given balance.
      @param initialBalance the initial balance
   */
   public BankAccount(double initialBalance)
   {  
      balance = initialBalance;
   }

   /**
      Deposits money into the bank account.
      @param amount the amount to deposit
   */
   public void deposit(double amount) 
   {  
      balance = balance + amount;
   }

   /**
      Withdraws money from the bank account.
      @param amount the amount to withdraw
   */
   public void withdraw(double amount) 
   {  
      balance = balance - amount;
   }

   /**
      Gets the current balance of the bank account.
      @return the current balance
   */
   public double getBalance()
   {  
      return balance; 
   }

   /**
      Transfers money from the bank account to another account
      @param amount the amount to transfer
      @param other the other account
   */
   public void transfer(double amount, BankAccount other)
   {  
      withdraw(amount);
      other.deposit(amount);
   }


}

SavingsAccount.java

/**
   An account that earns interest at a fixed rate.
*/
public class SavingsAccount extends BankAccount
{  
   private double interestRate;   
   /**
      Constructs a bank account with a given interest rate.
      @param rate the interest rate
   */
   public SavingsAccount(double rate) 
   {  
      interestRate = rate;
   }

   /**
      Adds the earned interest to the account balance.
   */
   public void addInterest() 
   {  
      double interest = getBalance() * interestRate / 100;
      deposit(interest); 
   }

}

CheckingAccount.java

/**
   A checking account that charges transaction fees.
*/
public class CheckingAccount extends BankAccount
{  
   private int transactionCount;
   private static final int FREE_TRANSACTIONS = 3;
   private static final double TRANSACTION_FEE = 2.0;
   /**
      Constructs a checking account with a given balance.
      @param initialBalance the initial balance
   */
   public CheckingAccount(double initialBalance)
   {  
      // Construct superclass
      super(initialBalance);

      // Initialize transaction count
      transactionCount = 0; 
   }

   public void deposit(double amount) 
   {  
      transactionCount++;
      // Now add amount to balance 
      super.deposit(amount); 
   }

   public void withdraw(double amount) 
   {  
      transactionCount++;
      // Now subtract amount from balance 
      super.withdraw(amount); 
   }

   /**
      Deducts the accumulated fees and resets the
      transaction count.
   */
   public void deductFees()
   {  
      if (transactionCount > FREE_TRANSACTIONS)
      {  
         double fees = TRANSACTION_FEE *
               (transactionCount - FREE_TRANSACTIONS);
         super.withdraw(fees);
      }
      transactionCount = 0;
   }

}

AccountTester.java

/**
   This program tests the BankAccount class and
   its subclasses. 
*/
public class AccountTester
{  
   public static void main(String[] args)
   {  
      SavingsAccount momsSavings 
            = new SavingsAccount(0.5);

      CheckingAccount harrysChecking
            = new CheckingAccount(100);

      momsSavings.deposit(10000);

      momsSavings.transfer(2000, harrysChecking);     
      harrysChecking.withdraw(1500);
      harrysChecking.withdraw(80);      

      momsSavings.transfer(1000, harrysChecking);
      harrysChecking.withdraw(400);      

      // Simulate end of month
      momsSavings.addInterest();
      harrysChecking.deductFees();

      System.out.println("Mom's savings balance: "
            + momsSavings.getBalance());
      System.out.println("Expected: 7035");

      System.out.println("Harry's checking balance: "
            + harrysChecking.getBalance());
      System.out.println("Expected: 1116");
   }
}

Demo2:Viewing the Accounts

InvestmentFrame.java

public class InvestmentFrame extends JFrame
{
   public InvestmentFrame()
   {
      account = new BankAccount(INITIAL_BALANCE);

      // Use instance fields for components
      label = new JLabel(''balance: '' + account.getBalance());

      // Use helper methods
      createButton();
      createPanel();
      setSize(FRAME_WIDTH, FRAME_HEIGHT);
   }
   private void createButton()
   {
      ActionListener listener = new AddInterestListener();
      button.addActionListener(listener);
      button = new JButton(''Add Interest'');
   }
   private void createPanel()
   {
      panel = new JPanel();
      panel.add(button);
      panel .add(label);
      add(panel);
   }
   private JButton button;
   private JLabel label;
   private JPanel panel;
   private BankAccount account;
}

InvestmentViewer2.java

public class InvestmentViewer2
{
   public static void main(String[] args)
   {
      JFrame frame = new InvestmentFrame();
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.setVisible(true);
   }
}

Demo3:Text Input from a GUI

InvestmentFrame.java (text Input version)

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;

/**
   A frame that shows the growth of an investment with variable interest.
*/
public class InvestmentFrame extends JFrame
{

   private JLabel rateLabel;
   private JTextField rateField;
   private JButton button;
   private JLabel resultLabel;
   private JPanel panel;
   private BankAccount account;

   private static final int FRAME_WIDTH = 450;
   private static final int FRAME_HEIGHT = 100;

   private static final double DEFAULT_RATE = 5;
   private static final double INITIAL_BALANCE = 1000;   
   public InvestmentFrame()
   {  
      account = new BankAccount(INITIAL_BALANCE);

      // Use instance fields for components 
      resultLabel = new JLabel("balance: " + account.getBalance());

      // Use helper methods 
      createTextField();
      createButton();
      createPanel();

      setSize(FRAME_WIDTH, FRAME_HEIGHT);
   }

   private void createTextField()
   {
      rateLabel = new JLabel("Interest Rate: ");

      final int FIELD_WIDTH = 10;
      rateField = new JTextField(FIELD_WIDTH);
      rateField.setText("" + DEFAULT_RATE);
   }

   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);
            resultLabel.setText(
                  "balance: " + account.getBalance());
         }            
      }

      ActionListener listener = new AddInterestListener();
      button.addActionListener(listener);
   }

   private void createPanel()
   {
      panel = new JPanel();
      panel.add(rateLabel);
      panel.add(rateField);
      panel.add(button);
      panel.add(resultLabel);      
      add(panel);
   }

}

InvestmentFrame.java (text are version)

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

/**
   A frame that shows the growth of an investment with variable interest.
*/
public class InvestmentFrame extends JFrame
{

   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;   

   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);
   }

   private void createTextField()
   {
      rateLabel = new JLabel("Interest Rate: ");

      final int FIELD_WIDTH = 10;
      rateField = new JTextField(FIELD_WIDTH);
      rateField.setText("" + DEFAULT_RATE);
   }

   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);
   }

   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);
   }

}


Review Exercises

R10.4. Identify the superclass and the subclass in each of the following pairs of classes.

(a) Employee, Manager

(b) Polygon, Triangle

(c) GraduateStudent, Student

(d) Person, Student

(e) Employee, GraduateStudent

(f) BankAccount, CheckingAccount

(g) Vehicle, Car

(h) Vehicle, Minivan

(i) Car, Minivan

(j) Truck, Vehicle

R10.5. Suppose the class Sub extends the class Sandwich. Which of the following assignments are legal?

 Sandwich x = new Sandwich();
Sub y = new Sub();

(a) x = y;

(b) y = x;

(c) y = new Sandwich();

(d) x = new Sub()

R10.9. Which of these conditions returns true? Check the Java documentation for the inheritance patterns.

(a) Rectangle r = new Rectangle(5, 10, 20, 30);

(b) if (r instanceof Rectangle) …

(c) if (r instanceof Point) …

(d) if (r instanceof Rectangle2D.Double) …

(e) if (r instanceof RectangularShape) …

(f) if (r instanceof Object) …

(g) if (r instanceof Shape) …

R10.17. Why are public fields dangerous? Are public static fields more dangerous than public instance fields?

R10.18. What is the difference between a label, a text field, and a text area?


Programming Exercises

P10.3. Implement a subclass Square that extends the Rectangle class. In the constructor, accept the x- and y-positions of the center and the side length of the square. Call the setLocation and setSize methods of the Rectangle class. Look up these methods in the documentation for the Rectangle class. Also supply a method getArea that computes and returns the area of the square. Write a sample program that asks for the center and side length, then prints out the square (using the toString method that you inherit from Rectangle) and the area of the square.

You need to supply the Square class.

Use the following class as your tester class:

/**
   This class tests the Square class.
*/
public class SquareTester
{
   public static void main(String[] args)
   {
      Square sq = new Square(10, 20, 30);
      System.out.println(sq.toString());
      System.out.println(''Expected: Square[x=-5,y=5,width=30,height=30]'');
      System.out.println(''Area: '' + sq.getArea());
      System.out.println(''Expected: 900'');
   }
}

P10.5. Make a class Employee with a name and salary. Make a class Manager inherit from Employee. Add an instance field, named department, of type String. Supply a method toString that prints the manager's name, department, and salary. Make a class Executive inherit from Manager. Supply appropriate toString methods for all classes. Supply a test program that tests these classes and methods.

Use the following class as your tester class:

/**
   This program tests the Employee class and its subclasses.
*/
public class EmployeeTester
{
   public static void main(String[] args)
   {
      Employee e = new Employee(''Edgar'', 65000);
      Manager m = new Manager(''Mary'', 85000, ''Engineering'');
      Executive v = new Executive(''Veronica'', 105000, ''Engineering'');
      System.out.println(e);
      System.out.println(''Expected: Employee[name=Edgar,salary=65000.0]'');
      System.out.println(m);
      System.out.println(''Expected: Manager[super=Employee[
            name=Mary,salary=85000.0],department=Engineering]'');
      System.out.println(v);
      System.out.println(''Expected: Executive[super=Manager[
            super=Employee[name=Veronica,salary=105000.0],
            department=Engineering]]'');
   }
}

P10.16. Write a program that prompts the user to enter the x- and y-positions of the center and a radius. When the user clicks a “Draw” button, draw a circle with that center and radius in a component.

Use the following class as your main class:

import javax.swing.JFrame;
/**
   Prompts the user to enter the x- and y-positions of the center and a radius.
   When the user clicks a ''Draw'' button, draw a circle with that center and
   radius in a component.
/*
public class CircleDrawer
{
   public static void main(String[] args)
   {
      JFrame frame = new CircleDrawerFrame();
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.setTitle(''CircleDrawer'');
      frame.setVisible(true);
   }
}

Use the following class in your solution:

import javax.swing.JComponent;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;
/**
   Displays a circle at a given position.
*/
public class CircleDrawerComponent extends JComponent
{
   public CircleDrawerComponent()
   {
      x = 0;
      y = 0;
      radius = 0;
      circle = null;
   }
   public void setPositionAndSize(int aX, int aY, int aRadius)
   {
      x = aX;
      y = aY;
      radius = aRadius;

      // the circle that the pai ntComponent method draws
      circle = new Ellipse2D.Double(
            x - radius, y - radius, radius * 2, radius * 2);
      repaint();
   }
   public void paintComponent(Graphics g)
   {
      if (circle == null) return;
      Graphics2D g2 = (Graphics2D) g;
      g2.draw(ci rcle);
   }
   private Ellipse2D.Double circle;
   private int x;
   private int y;
   private int radius;
}

P10.19. Write a program that draws a clock face with a time that the user enters in two text fields (one for the hours, one for the minutes).

Hint: You need to determine the angles of the hour hand and the minute hand. The angle of the minute hand is easy: The minute hand travels 360 degrees in 60 minutes. The angle of the hour hand is harder; it travels 360 degrees in 12 Χ 60 minutes.

Use the following class as your main class:

import javax.swing.JFrame;
/**
   This program displays a clock face with a time that the user specified.
*/
public class ClockViewer
{
   public static void main(String[] args)
   {
      JFrame frame = new ClockViewerFrame();
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.setTitle(''ClockViewer'');
      frame.setVisible(true);
   }
}