Chapter 9
Interfaces and Inheritance

Copyright © 2004 by Stuart Reges and Marty Stepp

9.1 Introduction

In this chapter we will explore two of the most important techniques provided by the Java language to write better structured solutions. Interfaces allow us to treat several different classes of objects the same way, while inheritance allows us to structure our classes so that we don't have to write the same code multiple times.

9.2 Interfaces

Consider the Stock class example from the last chapter. Stocks are not the only type of financial asset that investors might have in their financial portfolios. Other investments might include mutual funds, real estate, or cash. Though each of these types of assets is unique, they do have common characteristics. Most importantly, each has a certain current market value. In our example, stock's market value is the total number of shares purchased times the current price per share. Real estate's market value might depend on the current interest rate. Cash is always worth exactly its own amount.

If we were writing additional code to manage many types of financial assets, we might write classes like MutualFund, Cash, and so on. Perhaps we'd want to gather and store a person's collection of assets in an array. But arrays can only hold elements of the same type, so we would need one array for Stocks, one for MutualFunds, and so on. This is unnecessarily bulky and inconvenient. Also, our code to examine and manage the finances would have to treat each type of asset separately, and it could not take advantage of any similarity between the types of assets.

It would be convenient to be able to treat any asset the same way, insofar as they share similar functionality. For example, every asset has a market value, so it would be nice to be able to put all a person's assets into one large array, and then to be able to ask any asset for its market value, without worrying about exactly which type of asset it is.

One hurdle is that different assets compute their market value in different ways. Stocks' values are based on the current share price, while the value of cash depends only on how much cash the person has.

Java has a construct called an interface that can represent a common ground between several classes. Think of an interface as a set of qualifications that can be imposed on a class. We could write an interface to represent the common functionality of all financial assets--the ability to ask for their market value, and the ability to ask for the amount of profit or loss on the asset.

Interface

A set of methods that classes can promise to implement, allowing those classes to be treated similarly in your code.

Let's decide that asking for an asset's market value is achieved by calling its getMarketValue method, and asking for an asset's profit or loss is achieved by calling its getProfit method, so our interface will demand that all assets have these methods. The interface is a way of saying, "classes that want to consider themselves assets must have a getMarketValue and getProfit method."

The code for an interface looks like a class, but it can only contain methods' names, along with their parameters and return types. Interfaces don't specify how their methods are implemented--only the names and signatures of the methods. Our interface for financial assets would be saved into a file named Asset.java and might look like this:

// This interface represents financial assets that investors hold. public interface Asset { public double getMarketValue(); public double getProfit(); }

Now, classes can "certify" that they are Assets, by declaring that they obey the interface's requirements and by implementing the two methods. A class indicates that it is qualified to be an Asset by writing implements Asset in its class header, just after the class name. We'll do this to our Stock class:

    public class Stock implements Asset {

To fit this interface, our Stock class from the last chapter must undergo a few other changes. First of all, the market value and profit of a stock are determined by the current share price. Our Stock code asked for the current share price as an argument to its getProfit method. Since the getProfit method may not accept any arguments any more if we wish to implement the interface, we'll instead store the current share price as a data field in the Stock object. We'll supply a setCurrentPrice mutator method that can be called to set its proper value.

public class Stock implements Asset {
    ...

    private double currentPrice;  // current price per share
    ...

    // Sets the current price per share to be the given amount.
    // Precondition: amount >= 0.0
    public void setCurrentPrice(double currentPrice) {
        if (currentPrice < 0.0)
            throw new IllegalArgumentException("negative price");

        this.currentPrice = currentPrice;
    }

Now that we have our currentPrice field, we can use it to implement the parameterless getMarketValue and getProfit methods needed by the Asset interface.

    // Returns the current market value of the shares of this Stock.
    public double getMarketValue() {
        return this.numShares * this.currentPrice;
    }

    // Returns the total profit or loss earned on the shares of this stock.
    public double getProfit() {
        return this.getMarketValue() - this.totalCost;
    }

While we're making improvements to Stock, let's also add a second constructor that accepts an initial number of shares, total cost, and current share price. This will help us quickly initialize Stock objects, which will be useful in later examples.

Here's the new entire Stock class, after all previously mentioned modifications:

// A Stock object represents purchases of shares of a particular stock. public class Stock implements Asset { private String symbol; // stock symbol, such as "YHOO" private int numShares; // total number of shares purchased private double totalCost; // total cost for all shares purchased private double currentPrice; // current price per share // Creates a new Stock with the given symbol and no shares purchased. // Precondition: symbol != null public Stock(String symbol) { this(symbol, 0, 0.00, 0.00); } // Creates a new Stock with the given symbol and shares purchased, // with the given current price per share. // Precondition: symbol != null && numShares >= 0 && // totalCost >= 0.0 && currentPrice >= 0.0 public Stock(String symbol, int numShares, double totalCost, double currentPrice) { if (symbol == null || numShares < 0 || totalCost < 0.0 || currentPrice < 0.0) throw new IllegalArgumentException("null symbol"); this.symbol = symbol; this.numShares = numShares; this.totalCost = totalCost; this.currentPrice = currentPrice; } // Returns the current market value of the shares of this Stock. public double getMarketValue() { return this.numShares * this.currentPrice; } // Returns the total profit or loss earned on the shares of this stock. public double getProfit() { return this.getMarketValue() - this.totalCost; } // Sets the current price per share to be the given amount. // Precondition: amount >= 0.0 public void setCurrentPrice(double currentPrice) { if (currentPrice < 0.0) throw new IllegalArgumentException("negative price"); this.currentPrice = currentPrice; } // Records a purchase of the given number of shares of this stock // at the given price per share. // Precondition: numShares >= 0 && pricePerShare >= 0.00 public void purchase(int numShares, double pricePerShare) { if (numShares < 0 || pricePerShare < 0) throw new IllegalArgumentException("negative shares or price"); this.numShares += numShares; this.totalCost += numShares * pricePerShare; } // Returns a string representation of this Stock. public String toString() { String result = this.symbol; result += " ( " + this.numShares + " shares, $ " + this.totalCost; // add an extra 0 to the end of the string, if needed if (result.indexOf(".") == result.length() - 2) result += "0"; result += " total cost )"; return result; } }

Now that we have a suitable Stock class that implements Asset, let's write a Cash class that also implements this interface. A Cash asset is simply an amount of money. (We'll allow negative amounts.)

It is trivial to decide the market value of the Cash (exactly equal to how much Cash we have) and the profit or loss on the Cash (always $0.00, because money is money). We'll also add setAmount and toString methods for convenience.

Here is a complete Cash class that implements the Asset interface:

// Represents an amount of money held by an investor. public class Cash implements Asset { private double amount; // amount of money held by investor // Constructs an amount of cash equal to the given amount of dollars. public Cash(double amount) { this.amount = amount; } // Returns the amount of cash held. public double getMarketValue() { return this.amount; } // Returns the profit on this cash--since cash is a // fixed asset, it never has any profit or loss. public double getProfit() { return 0.00; } // Sets the amount of cash held to the given amount. public void setAmount(double amount) { this.amount = amount; } // Returns a string representation of this Cash. public String toString() { String result = "Cash ( $ " + this.amount; if (result.lastIndexOf(".") == result.length() - 2) result += "0"; result += " )"; return result; } }

If you declare that your class implements an interface, your class must now have an implementation of every method in that interface, or else it will not compile. For example, if we try to lie and certify a class as an Asset that doesn't have a way to get its market value or profit, the compiler will complain:

public class EmptyClass implements Asset { // How incomplete I am! }

The compiler would give this error when trying to compile EmptyClass.java:

C:\document\EmptyClass.java:1: EmptyClass is not abstract and does not override abstract method getMarketValue() in Asset public class EmptyClass implements Asset { ^ C:\document\EmptyClass.java:1: EmptyClass is not abstract and does not override abstract method getProfit() in Asset public class EmptyClass implements Asset { ^ 2 errors

The error message is a bit cryptic, but the gist of it is that the compiler is complaining because EmptyClass objects don't have a getMarketValue or getProfit method, so they cannot be assets. The general syntax for implementing an interface in a class is the following:

    public class <name> implements <name> {
        ...
    }

If we wanted to write more interfaces of our own, like Asset, the general syntax for declaring an interface is the following:

    public interface <name> {
        public <type> <name>(<type> <name>, ..., <type> <name>);
        public <type> <name>(<type> <name>, ..., <type> <name>);
        ...
        public <type> <name>(<type> <name>, ..., <type> <name>);
    }

It's important to understand that an interface isn't a new type of objects like a class is. It isn't legal to try to create objects of an interface. For example, this code:

    Asset a = new Asset();

leads to the following compiler error message:

    C:\document\StockManager.java:29: Asset is abstract; cannot be instantiated
        Asset a = new Asset();

9.3 Polymorphism

The key benefit of interfaces is that they let us treat related classes in the same way. Even though we can't create objects of type Asset, we can create arrays or variables of type Asset. Such an array or variable can refer to any object that implements the Asset interface.

public class AssetExample { public static void main(String[] args) { Asset[] investments = new Asset[4]; investments[0] = new Stock("MSFT", 10, 300.00, 27.50); investments[1] = new Cash(500.00); investments[2] = new Cash(1200.54); investments[3] = new Stock("INTC", 30, 620.00, 23.00); for (int i = 0; i < investments.length; i++) { System.out.println(investments[i]); System.out.print("Market value is: " + investments[i].getMarketValue()); System.out.println(", profit is: " + investments[i].getProfit()); System.out.println(); } } }

This code produces the following output:

MSFT ( 10 shares, $ 300.00 total cost ) Market value is: 275.0, profit is: -25.0 Cash ( $ 500.00 ) Market value is: 500.0, profit is: 0.0 Cash ( $ 1200.54 ) Market value is: 1200.54, profit is: 0.0 INTC ( 30 shares, $ 620.00 total cost ) Market value is: 690.0, profit is: 70.0

This deceptively simple code is actually doing some very powerful things. For starters, we are able to create an array that holds objects of two different types. Second, our for loop is able to print each asset in the array (using its toString method), as well as ask for its market value.

Keep in mind that the actual toString, getMarketValue or getProfit method called could be one of two choices: the version in the Stock class or the version in the Cash class. Java does the right thing and calls the correct method, depending on what kind of asset is stored in each index of the array. Our for loop didn't have to check which type of asset was in each index; it was able to treat all the assets in the same way.

The ability for the same code to be used with several different types of objects is called polymorphism. Polymorphism is useful because it allows us to implement code that is more general and works correctly with a broader range of objects. In Java, one way to achieve polymorphism is by using interfaces.

Polymorphism

The ability for the same code to be used with several different types of objects, possibly behaving differently depending on the type of objects used.

9.4 Inheritance

Sometimes we wish to create a new class that is similar to an existing class. Consider the example of creating a class to represent ownership of stocks that pay dividends. We don't want to add dividend code to our existing Stock class, because not all stocks have dividend payments. But the code for such a class would look very similar to that of the Stock class. Here is a possible implementation:

// A DividendStock object models shares of stocks with dividend payments. public class DividendStock implements Asset { private int numShares; private double totalCost; private double currentPrice; private String symbol; private double dividends; public DividendStock(String symbol, double currentPrice) { this.symbol = symbol; this.currentPrice = currentPrice; this.numShares = 0; this.totalCost = 0.00; this.dividends = 0.00; } public double getMarketValue() { return this.numShares * this.currentPrice; } public double getProfit() { return this.dividends + this.getMarketValue() - this.totalCost; } public void payDividend(double amount) { this.dividends += amount; } public void recordPurchase(int numShares, double pricePerShare) { this.numShares += numShares; this.totalCost += numShares * pricePerShare; } public void setCurrentPrice(double currentPrice) { this.currentPrice = currentPrice; } }

Notice how much DividendStock has in common with Stock. It might seem tempting to represent this similarity with an interface, such as our Asset interface. But there's more in common here than just the names of the methods. Their actual implementations are the same. Because of this, the code for DividendStock is redundant compared to that of the Stock class, and we'd like to get rid of this redundancy.

Also, conceptually speaking, an interface doesn't accurately represent the relationship between a dividend stock and a normal stock. Dividend-paying stocks are actually a subtype of stocks, representing one particular and specific kind of stock. Every dividend stock is a stock, but not all stocks are dividend stocks. It would be nice to be able to represent this "is-a" relationship in some way in the code.

Java provides a mechanism called inheritance that can help us remove redundant code like this. Inheritance allows the programmer to specify a parent-child relationship between two classes.

Inheritance

A parent-child relationship between two classes, where objects of the child class receive their own copy of the data fields and methods of the parent class.

The child, or subclass, receives all of the state and behavior of its parent, or superclass. The child can then add existing state and behavior of its own, or it can replace its inherited behavior with new behavior as needed. A Java class can have only one parent; it is not possible to extend more than one class. This is called single inheritance.

Superclass or Base Class

The parent in an inheritance relationship. A class can only have one superclass.

Subclass or Derived Class

The child in an inheritance relationship. One parent may have many children.

In our case, we'd like DividendStock to be a subclass of Stock, inheriting all of Stock's state and behavior. Then our DividendStock class can add new behavior for dividends.

To specify that DividendStock is a subclass of Stock, and that it should receive all of the data fields and methods from the Stock class, we write extends Stock in DividendStock's class header. We don't need to say implements Asset again in the header for DividendStock, because this is already covered by the Stock superclass.

    public class DividendStock extends Stock {
      ...
    }

The general syntax to specify one class as the child (subclass) of another is the following:

    public class <name> extends <name> {
        ...
    }

Once we've made DividendStock extend Stock, it means that DividendStock now receives symbol, numShares, totalCost and currentPrice data fields, and it now has methods named getCurrentPrice, getMarketValue, getNumShares, getProfit, getSymbol, getTotalCost, recordPurchase, setCurrentPrice, and toString. We say that DividendStock "inherits" these things from its superclass, Stock.

When a class inherits data fields and methods, they now become a part of that class's objects, even if we don't declare them explicitly. So we can now remove our declarations of the four data fields that come from Stock, as well as the methods that are identical to those in Stock, but DividendStock will still have all those fields and methods because of inheritance. As you may imagine, the DividendStock class will now be much shorter than it was before, and won't contain so much redundant code.

Now the majority of DividendStock's code is that which focuses on dividend payments. The only existing behavior from Stock that must change in DividendStock is the implementation of getProfit, which now depends on the total dividends paid.

9.4.1 Private Access and the super Keyword

One quirk of inheritance is that, while data fields and methods are inherited from a superclass into its subclass(es), constructors are not. This means that our DividendStock class must have a constructor of its own. We'd like to make our constructor set the symbol and currentPrice fields, just like the Stock constructor does, but it is illegal to do so:

    public class DividendStock extends Stock {
        private double dividends;

        public DividendStock(String symbol, double currentPrice) {
            this.symbol = symbol;              // This code does not work!
            this.currentPrice = currentPrice;  // This code does not work!
            this.numShares = 0;                // This code does not work!
            this.totalCost = 0.00;             // This code does not work!
            this.dividends = 0.00;
        }

Because the symbol and currentPrice fields are private in the Stock class, DividendStock can't see them. Unfortunately for us, private access in a superclass like Stock doesn't include for the subclasses like DividendStock. The following compiler errors result from trying to compile the previous code:

C:\document\DividendStock.java:5: symbol has private access in Stock this.symbol = symbol; ^ C:\document\DividendStock.java:6: currentPrice has private access in Stock this.currentPrice = currentPrice; ^ C:\document\DividendStock.java:7: numShares has private access in Stock this.numShares = 0; ^ C:\document\DividendStock.java:8: totalCost has private access in Stock this.totalCost = 0.00; ^ 4 errors

The only easy way to set the symbol and current price to their initial values is to have the DividendStock constructor call the constructor from the Stock class, and let it set the values. Calling the superclass's constructor has some other nice benefits, such as the fact that we don't have to check the symbol and currentPrice arguments for validity, because the Stock constructor will do this for us.

To call Stock's constructor from DividendStock's, we use the super keyword. The super keyword refers to the current class's superclass. Using it allows us to call a constructor or method from the superclass. To call the superclass's constructor, we write super, followed by the required arguments in parentheses.

    public DividendStock(String symbol, double currentPrice) {
        super(symbol, 0, 0.00, currentPrice);
        this.dividends = 0.00;
    }

The general syntax for using the super keyword to refer to a constructor or method is the following:

    super(<name>, ..., <name>);         // constructor
    super.<name>(<name>, ..., <name>);  // method

9.4.2 Overriding Behavior in a Subclass

A DividendStock should include dividend payments as part of its market value. This information should also be taken into account when computing its profit. This change means that DividendStock does not want to inherit the getMarketValue behavior from Stock, which only takes into account the total cost and market value. We can write a new version of getMarketValue for DividendStock to replace the version that was inherited from Stock.

    public double getMarketValue() {
        return this.numShares * this.currentPrice + this.dividends;
    }

This idea of replacing behavior from the superclass is called overriding.

Override

Implementing a new version of a method inherited from a superclass, replacing the superclass's version.

If we really want to reduce redundancy, we can notice that our new getMarketValue still performs the same calculation from the old getMarketValue (number of shares * current price per share) as part of its work. Therefore, we can use the super keyword to get the old getMarketValue method's value, then add the dividends to it to get the new market value.

    // Returns the total profit or loss earned on the shares of this stock.
    public double getMarketValue() {
        return super.getMarketValue() + this.dividends;
    }

You might think that we should also override the getProfit method to adjust for the dividends. However, interestingly we don't need to do this. Recall the implementation of getProfit from the Stock class:

    public double getProfit() {
        return this.getMarketValue() - this.totalCost;
    }

Notice how getProfit calls getMarketValue. We overrode getMarketValue, and because of polymorphism, calling getProfit on a DividendStock will use our new version of the getMarketValue method. Therefore getProfit already works the way we want, and we don't need to override it.

After implementing these changes, our DividendStock class looks like this:

// A DividendStock object models shares of stocks with dividend payments. public class DividendStock extends Stock { private double dividends; // amount of dividends paid // Constructs a new dividend stock with the given symbol and current share price. public DividendStock(String symbol, double currentPrice) { super(symbol, 0, 0.00, currentPrice); // call Stock constructor this.dividends = 0.00; } // Returns the total profit or loss earned on the shares of this stock. public double getMarketValue() { return super.getMarketValue() + this.dividends; } // Records the payment of a dividend on this stock of the given amount. public void payDividend(double amount) { this.dividends += amount; } }

9.5 Abstract Classes

If inheritance lets us specify classes as parents and children, interfaces may be like distant cousins: related, but without many details in common. There are situations where we want more of a sibling relationship--classes with common method names, like we get with interfaces, but also with some code shared between them, like we get with inheritance.

Let's consider the case where we want to write a third asset class to represent mutual funds. A mutual fund is a shared investment plan where investors place money into the hands of an investment firm. The firm then invests the money into various stocks and assets, and the profits are shared among the investors.

Mutual funds aren't really a subcategory of stocks, so it wouldn't be right to make a MutualFund class that extends Stock. Mutual funds are more like siblings of stocks--they have a lot of behavior and state in common, but not all. One major difference between a mutual fund and a stock is that it is possible to own partial shares of mutual funds. We'll represent this in our MutualFund class by making the number of shares a data field of type double, rather than int.

Here is an implementation of MutualFund that can be improved upon. We'll omit some things such as checking arguments' values and method header comments.

// A MutualFund object represents purchases of shares of a particular Mutual Fund. public class MutualFund implements Asset { private String symbol; private double numShares; // partial shares are allowed private double totalCost; private double currentPrice; public MutualFund(String symbol, double currentPrice) { this.symbol = symbol; this.currentPrice = currentPrice; this.numShares = 0.0; this.totalCost = 0.00; } public double getNumShares() { return this.numShares; } public double getMarketValue() { return this.numShares * this.currentPrice; } public double getProfit() { return getMarketValue() - this.totalCost; } public void recordPurchase(double numShares, double pricePerShare) { this.numShares += numShares; this.totalCost += numShares * pricePerShare; } public void setCurrentPrice(double currentPrice) { this.currentPrice = currentPrice; } }

One thing you'll notice is that the code for the MutualFund class is very similar to that of the Stock class. They aren't identical, but they share so much common code that we'd like to get rid of the redundancy somehow. Making MutualFund extend Stock would be wrong for a few reasons, mainly that it's illegal for us to change the type of a data field or method that we inherit, which would prevent us from changing numShares from int to double.

MutualFunds aren't a subclass of Stocks, but they do have things in common that we can represent by giving the two a common parent class. We can create a third class that represents everything that stocks and mutual funds have in common. This class will become the parent for both Stock and MutualFund. We'll call it ShareAsset, because both stocks and mutual funds are assets divided into shares.

The common code between Stock and MutualFund is the code for the symbol, total cost, and current price. Notice that we have to remove anything that refers to number of shares, because this is implemented differently by each of Stock and MutualFund. We'll include accessor methods to get each field's value, because this will be necessary later.

public class ShareAsset { private String symbol; private double totalCost; private double currentPrice; public ShareAsset(String symbol, double totalCost, double currentPrice) { this.symbol = symbol; this.totalCost = totalCost; this.currentPrice = currentPrice; } public String getSymbol() { return this.symbol; } public double getTotalCost() { return this.totalCost; } public double getCurrentPrice() { return this.currentPrice; } public void setCurrentPrice(double currentPrice) { this.currentPrice = currentPrice; } }

A ShareAsset isn't really a type of asset that a person can buy; it's just a fictional idea created in our code. If we want to create classes like this that shouldn't be used directly by outside code, but should only serve as a superclass for inheritance, we can call the class abstract. Writing abstract in the class's header will specify that a class is abstract and cannot be used directly to construct objects.

    public abstract class ShareAsset implements Asset {
        ...
    }

An attempt to create a ShareAsset object will produce this compiler error, if ShareAsset was declared to be abstract:

    C:\document\StockManager.java:55: ShareAsset is abstract; cannot be instantiated
          ShareAsset asset = new ShareAsset("MSFT", 20, 27.46);
          ^
    1 error

Abstract classes can also behave like interfaces, in that they can demand behavior be implemented by any of their subclasses. Such required subclass behaviors are called abstract methods. One improvement we can make to our ShareAsset class is to demand that any subclass implement a getMarketValue method, because each will need this to implement the Asset interface. To make such a demand, we declare an abstract getMarketValue method:

    public abstract double getMarketValue();

An abstract method is declared with a header similar to regular methods, but with the keyword "abstract" after the public modifier. The other difference about abstract methods is that they do not have method bodies--they only have a semicolon, which means that the behavior is specified in each subclass. An abstract class can contain both abstract and non-abstract methods. By contrast, every method in an interface is technically abstract, and they can be declared with the abstract keyword if so desired.

The general syntax for abstract method declarations is the following:

    public abstract <type> <name>(<type> <name>, ..., <type> <name>);

We can't declare getNumShares as abstract, because it has a different return type in Stock and in MutualFund.

Because an abstract class can contain normal data fields and methods with implementation, and it can also contain abstract methods without implementation, abstract classes can be thought of as hybrids between Java classes and interfaces. One important difference between interfaces and abstract classes is that a class may choose to implement arbitrarily many interfaces, but it can only extend one abstract class.

Abstract Class

A Java class that serves only as a superclass-and-interface for other classes, not actually to create objects of its type.

One last modification we'll make to ShareAsset is to include an addCost method, which we'll use to add a given amount to the asset's total cost. We will need this because purchases on Stocks and MutualFunds need to update the totalCost data field, but they cannot do so directly since it is private.

Our abstract ShareAsset class looks like this:

public abstract class ShareAsset implements Asset { private String symbol; private double totalCost; private double currentPrice; public ShareAsset(String symbol, double totalCost, double currentPrice) { this.symbol = symbol; this.totalCost = totalCost; this.currentPrice = currentPrice; } public String getSymbol() { return this.symbol; } public double getTotalCost() { return this.totalCost; } public double getCurrentPrice() { return this.currentPrice; } public double getProfit() { return this.getMarketValue() - this.getTotalCost(); } public void addCost(double cost) { this.totalCost += cost; } public void setCurrentPrice(double currentPrice) { this.currentPrice = currentPrice; } public abstract double getMarketValue(); }

Now we can modify the Stock class to take advantage of ShareAsset. Notice that we must implement getMarketValue, or else we receive an error.

public class Stock extends ShareAsset { private int numShares; public Stock(String symbol, double currentPrice) { super(symbol, 0.00, currentPrice); this.numShares = 0; } public double getMarketValue() { return this.numShares * getCurrentPrice(); } public void recordPurchase(int numShares, double pricePerShare) { this.numShares += numShares; addCost(numShares * pricePerShare); } }

MutualFund gets a similar makeover:

public class MutualFund extends ShareAsset { private double numShares; public MutualFund(String symbol, double currentPrice) { super(symbol, currentPrice); this.numShares = 0.0; } public double getMarketValue() { return this.numShares * getCurrentPrice(); } public double getNumShares() { return this.numShares; } public void recordPurchase(double numShares, double pricePerShare) { this.numShares += numShares; addCost(numShares * pricePerShare); } }
Stuart Reges
and Marty Stepp
Last modified: Sun Feb 13 23:59:59 PST 2005