The first assignment statement for item1 is no surprise; it assigns an Item object to an Item variable. But that second assignment statement—assigning a SaleItem object to an Item variable? How can that possibly work? What mad sorcery is this?
Remember, we’re talking about an is-a relationship. A SaleItemis anItem. That’s why it’s legal to make the assignment. That is called polymorphism—the ability to assign a child class object to a parent class variable.
Take a look at the System.out.println statements that produced that output. The first one uses Item’s toString method to print item1 with its name, SKU, and price. The second one uses SaleItem’s toString method to print item2’s name, SKU, price and discount rate.
The answer is dynamic binding. At compile time, both item1 and item2 have the Item data type. But at run time, the JVM looks at the actual object that item2 refers to and finds that it has the SaleItem data type, and it uses SaleItem’s toString method.
Rye Bread: $3.95
Tomato Soup: $1.23 - you save $0.06
Canned Lima Beans: $2.52 - you save $0.46
Frozen Pizza: $5.19 - you save $0.71
Organic Salsa: $3.79
for(Item food: foods){System.out.printf("%s: ", food.getName());if(food is a sale item){
discounted price is getPrice()*(1-getDiscount());
amount saved is getPrice()*getDiscount();
display discounted price and amount saved;}else{
display getPrice();}}
Note that the for loop variable is an Item, because we have told the compiler that foods is an array of Item. Here’s the big question: how do we determine—at run time—if an array element is a SaleItem or an Item? We use the instanceof operator, which takes the form:
PolyArray.java:17: error: cannot find symbol
food.getDiscount();
^
symbol: method getDiscount()
location: variable food of type Item
Why can’t the compiler find getDiscount? The answer is in variable food of type Item. As far as the compiler is concerned, food is an Item, and that class does not have a getDiscount method in it.
At compile time, the compiler sees the superclass variable as having the superclass data type. In the preceding code, the compiler says that myItem has data type Item.
At run time, the compiler uses the actual data type of the object. When you say:
ListingA.3.9.
System.out.println(myItem.toString());
the JVM will see that myItem contains a reference to a SaleItem object and will invoke SaleItem’s toString method.
The compiler won’t let you call a method that exists only in the subclass on a superclass variable. This won’t work:
This exercise will let you practice polymorphism and dynamic binding. Implement the Bicycle, ElectricBicycle, and CargoBicycle classes. (These are not defined in the same way as in the preceding text.) The parent Bicycle class has these attributes and methods:
This exercise will let you practice polymorphism and dynamic binding. It uses the Account, SavingsAccount, and CreditCardAccount classes you developed in Exercise A.2.2.3. Instead of creating a customer with multiple accounts, create an array of these accounts:
A SavingsAccount number 30507 with a balance of $4,500 and an APR of 1.5\%
A CreditCardAccount number 51782737 with a balance of $7,000.00, APR of 8\%, and credit limit of $1000.00
A CreditCardAccount number 629553328 with a balance of $1,500.00, an APR of 7.5\%, and a credit limit of $5,000
A CreditCardAccount number 4977201043L with a balance of -$5,000.00, an APR of 7\%, and a credit limit of $10,000 (The L after the account number lets the compiler know that the account number is a long integer.)