+ All Categories
Home > Documents > mypages.valdosta.edu · Web viewCS 1302 – Chapter 11. Inheritance & Polymorphism. Reference...

mypages.valdosta.edu · Web viewCS 1302 – Chapter 11. Inheritance & Polymorphism. Reference...

Date post: 21-Jun-2020
Category:
Upload: others
View: 1 times
Download: 0 times
Share this document with a friend
38
CS 1302 – Chapter 11 Inheritance & Polymorphism Reference Sections 11.1-11.15 11.1 – Introduction 1. Suppose we have the Dog class shown on the left and we need a new class, WolfDog on the right: The two classes are similar; they have the same instance variable and two methods that are identical. They also both have a bark method with the same signature, but a different implementation. Java provides a mechanism (called inheritance or subclassing) that allows us to write this new class, WolfDog in a way that we don’t have to rewrite the members that are the same. Thus, this technique supports code reuse. 2. We can write the WolfDog class as shown below on the right (We will consider constructors that accept arguments shortly. For now, each class has a no-arg constructor by default). 1
Transcript
Page 1: mypages.valdosta.edu · Web viewCS 1302 – Chapter 11. Inheritance & Polymorphism. Reference Sections 11.1-11.15. 11.1 – Introduction. Suppose we have the . Dog . class …

CS 1302 – Chapter 11Inheritance & Polymorphism

Reference Sections 11.1-11.15

11.1 – Introduction

1. Suppose we have the Dog class shown on the left and we need a new class, WolfDog on the right:

The two classes are similar; they have the same instance variable and two methods that are identical. They also both have a bark method with the same signature, but a different implementation. Java provides a mechanism (called inheritance or subclassing) that allows us to write this new class, WolfDog in a way that we don’t have to rewrite the members that are the same. Thus, this technique supports code reuse.

2. We can write the WolfDog class as shown below on the right (We will consider constructors that accept arguments shortly. For now, each class has a no-arg constructor by default).

1

Page 2: mypages.valdosta.edu · Web viewCS 1302 – Chapter 11. Inheritance & Polymorphism. Reference Sections 11.1-11.15. 11.1 – Introduction. Suppose we have the . Dog . class …

And use it:

3. More generally, suppose we have a class, A and we need a new class, B that is similar to A. Perhaps B requires the same instance variables and/or methods as A, but just needs to change things a bit. The technique we use allows us to define a new class, B by extending class A. In Java, we define B like this:

public class B extends A {

We call A the superclass and B a subclass. Note the following about the new class, B:

B can be created and used just as any class can. B inherits all of A’s members that are not private (i.e. public, protected and default visibility). This means

that all non-private members defined in A are automatically members of B without having to rewrite them (code reuse).

If B wants to change a method in A then it can override the method. This is done by writing the method in B with the same signature as the method in A, but with a different implementation.

B can add new members (but they are not available in A). An instance of B can be used anywhere an instance of A is required (but not the other way around).

We explore this useful technique throughout this chapter and the remainder of the course. In fact, there will not be a single day the remainder of the semester that we will not use inheritance.

11.2 – The protected and super Keywords

1. Suppose we define a class, A in a package named pack1. Then, any member of A that is declared with protected visibility is available:

To any other class in the same package (pack1). To any subclass of A defined in any package.

For example:

Note:

B inherits x because it is a subclass of A. E inherits x because it is a subclass of A even though it is in a

different package. C can access x because it in the same package. D cannot access x because it is in a different package.

2

Page 3: mypages.valdosta.edu · Web viewCS 1302 – Chapter 11. Inheritance & Polymorphism. Reference Sections 11.1-11.15. 11.1 – Introduction. Suppose we have the . Dog . class …

2. A subclass’s constructor can call a constructor in the superclass by using the super keyword in exactly the same way a constructor in a class can call another constructor in the same class with the this keyword:

It must be the first statement in the constructor There must be a constructor in the superclass with a signature matching the arguments to super.

Note that there are some other important details about super and subclass constructors that we will cover shortly.

3. For example: The name is declared protected in the Dog class meaning that it is inherited in the WolfDog class. Thus,

we can use it on the overridden bark method in the WolfDog class. The WolfDog constructor calls the Dog constructor, thus initializing the name.

11.3 – Example

1. Suppose we have a BasicAccount class, as shown below, that allows clients to deposit and withdraw money and at the end of the month, a service fee of $5 is charged and if the balance is less than 0, then a $25 overdraft fee is charged. Note that the balance field has protected visibility.

public class BasicAccount {protected double balance;private String name;

public BasicAccount(String name, double balance) {this.name = name; this.balance = balance;

}public double getBalance() { return balance; }public String getName() { return name; }

public void deposit(double amount) { balance += amount; }public void withdraw(double amount) { balance -= amount; }

public void endOfMonth() {balance -= 5.0;if(balance<0.0) balance -= 25.0;

}...

3

Page 4: mypages.valdosta.edu · Web viewCS 1302 – Chapter 11. Inheritance & Polymorphism. Reference Sections 11.1-11.15. 11.1 – Introduction. Suppose we have the . Dog . class …

}2. Now, suppose we need a GoldAccount class that is the same as BasicAccount except for two features:

GoldAccount needs an interest rate instance variable. The endOfMonth method applies the interest rate to the balance if the balance is zero or greater and

otherwise charges a $10 overdraft fee.

3. We can write the GoldAccount subclass as shown below:

Note: An instance variable, interestRate is introduced in the subclass that is not in the superclass. Similarly, the

getter for this variable is new in the subclass. The super(…) statement in the constructor calls the superclass constructor that matches the signature

(String, double). The endOfMonth method is overridden. This means that there is a method in the superclass is with the

same signature, but a different implementation. The endOfMonth method uses a balance variable that is inherited from the superclass, BasicAccount.

4. We can use the two classes as shown below:

BasicAccount GoldAccountBasicAccount ba = new BasicAccount("Leon",90.0);System.out.println("Account created: " + ba);ba.deposit(10.0);System.out.println("$10 deposited : " + ba);ba.endOfMonth();System.out.println("End of month : " + ba);

GoldAccount ga = new GoldAccount("Shay",90.0,0.1);System.out.println("Account created: " + ga);ga.deposit(10.0);System.out.println("$10 deposited : " + ga);ga.endOfMonth();System.out.println("End of month : " + ga);

Output Output4

Page 5: mypages.valdosta.edu · Web viewCS 1302 – Chapter 11. Inheritance & Polymorphism. Reference Sections 11.1-11.15. 11.1 – Introduction. Suppose we have the . Dog . class …

Account created: Basic: bal=$90.00, name=Leon$10 deposited : Basic: bal=$100.00, name=LeonEnd of month : Basic: bal=$95.00, name=Leon

Account created: Gold: bal=$90.00, name=Shay$10 deposited : Gold: bal=$100.00, name=ShayEnd of month : Gold: bal=$110.00, name=Shay

Note the following: The GoldAccount can use the deposit method defined in BasicAccount; it is inherited. The endOfMonth method operates differently with a BasicAccount and a GoldAccount.

11.4 – UML for Subclasses & protected members

1. The class diagram on the right shows a superclass-subclass relationship. Note:

We use a solid line with an open triangle at the end pointing to the superclass.

We use “#” to denote a member as having protected accessibility.

We usually do not show inherited methods in the subclass, though we can if it is helpful.

We say a GoldAccount is-a BasicAccount, but a BasicAccount is-not-a GoldAccount. We explore what this means as we continue through this chapter

Section 11.5 – The Object Class and its toString Method

1. Object is a concrete class in Java and it defines the toString method (also the equals method which we consider shortly, and other methods).

See: https://docs.oracle.com/javase/9/docs/api/java/lang/Object.html

2. Object is the superclass of every. If a class does not extend another class, then it automatically extends Object. For example:

public class Dog {}

is identical to:

public class Dog extends Object {}

Thus, Every class is-a Object. Every class inherits the toString method.

5

Page 6: mypages.valdosta.edu · Web viewCS 1302 – Chapter 11. Inheritance & Polymorphism. Reference Sections 11.1-11.15. 11.1 – Introduction. Suppose we have the . Dog . class …

6

Page 7: mypages.valdosta.edu · Web viewCS 1302 – Chapter 11. Inheritance & Polymorphism. Reference Sections 11.1-11.15. 11.1 – Introduction. Suppose we have the . Dog . class …

3. Example:

Thus: A Dog is-a Object A WolfDog is-a Dog A WolfDog is-a Object

So, in the past, when we write a toString method, we are actually overriding the Object classes toString method. And, when we define a subclass, we are overriding the superclasses toString method.

Homework:

1. In a warehouse, a SKU (stock keeping unit, pronounced skyew) is an identification for a particular item in the warehouse and is typically an alphanumeric code. In general, there are lots of properties a SKU would have, for example, the SKU code, description, dimensions, weight, etc. For this problem, we only consider the weight. Consider the following Sku class:

public class Sku {protected double weight;

public Sku(double weight) {this.weight = weight;

}

public double getWeight() {return weight;

}

public double cost() {return 2.0*weight;

}

@Overridepublic String toString() {

String msg = String.format("weight=%.1f, cost=$,.2f", weight, cost());return msg;

}}

Consider the following two classes:

RefrigeratedSku is a subclass of Sku which also defines a temperature property which is accepted in the constructor and also has getter. It should override the cost method so that the cost is 3 times the weight and in addition, there is a $5 surcharge unless the temperature is less than 40

7

Page 8: mypages.valdosta.edu · Web viewCS 1302 – Chapter 11. Inheritance & Polymorphism. Reference Sections 11.1-11.15. 11.1 – Introduction. Suppose we have the . Dog . class …

degrees in which case the surcharge is $10. It should also override the toString method.

FrozenSku is a subclass of RefrigeratedSku which overrides the cost method so that the cost is 3 times the weight and and in addition there is a $20 surcharge unless the temperature is less than 00 degrees in which case the surcharge is $30. It should also override the toString method.

a. Draw a class diagram that shows all three classes.b. Write the code for RefrigeratedSku class.c. Write the code for FrozenSku class.d. Write a snippet of code to test these classes.

Section 11.6 – Polymorphism & Dynamic Binding

1. Consider the example considered earlier, shown in the class diagram on the right. As shown below, we can create a GoldAccount but refer to it as a BasicAccount.

Note the following:

We can always use a super-type reference to refer to a sub-type instance. This is referred to as polymorphism. A super-type reference is a polymorphic reference because the reference variable can hold an instance of many different classes: BasicAccount and any subclasses.

The endOfMonth method that executes is determined by the instance type, not the reference type. In this case, the instance is GoldAccount. This is referred to as dynamic binding.

The reference type (BasicAccount) determines what methods are visible (can be called). Thus, getInterestRate cannot be called because it is not defined in the BasicAccount. A natural question would be why we would even want to use a super-type reference especially in light of the fact that we might not be able to access all the methods that the instance actually contains. We will answer that as we go along.

8

Page 9: mypages.valdosta.edu · Web viewCS 1302 – Chapter 11. Inheritance & Polymorphism. Reference Sections 11.1-11.15. 11.1 – Introduction. Suppose we have the . Dog . class …

2. Consider the example below. Note the following:

First, we create a WolfDog instance but give it a (supertype) Dog reference. When the bark method is called, the actual bark method that runs is determined by the actual type of

the object not the reference type. Thus, the WolfDog’s bark method is called (red arrow). Next, the run method is called. Since the WolfDog class does not define a run method, the JVM finds a

run method in the Dog superclass (blue arrow). Finally, the Dog reference, sam is assigned to an instance of a Dog and so the Dog class’s bark method is

called (green arrow). Thus, dynamic binding means that the the actual method that runs is determined at run-time by the instance of the object, not the reference type.

3. The JVM goes through a process like this to implement dynamic binding

Get the type of the instance.If ( instance contains a definition for the behavior )

Execute behaviorElse

Find behavior in superclass & execute

Thus, the method is bound to the call at run-time (dynamically).

4. Non-software example – In the figure on the right, Saxophone, Trumpet, and Trombone are subclasses of Horn and each one overrides the play method in a way that is appropriate for the specific type of instrument (instance). Thus, each plays notes differently. When the conductor gestures with his baton for the horn section to play he is referring to them polymorphically, however each horn plays according to what type of horn it actually is.

9

Page 10: mypages.valdosta.edu · Web viewCS 1302 – Chapter 11. Inheritance & Polymorphism. Reference Sections 11.1-11.15. 11.1 – Introduction. Suppose we have the . Dog . class …

5. Polymorphism and dynamic binding are really useful because they allow us to write code that uses supertypes that will operate on any subtypes (even ones that haven’t been written yet!). This gives programs flexibility and extensibility. It makes methods generic in a sense. It probably will take a long time before the usefulness and importance of this fully sinks in. They are one of the cornerstones of object-oriented programming.

Section 11.7 – Polymorphic Arrays

1. As shown below, we can create an array of BasicAccount which can also hold GoldAccounts, because a GoldAccount is-a BasicAccount.

Note the following:

As we iterate over accounts in the for loop above, each account has a BasicAccount reference type so we can only call methods defined (public and protected) in that class. Thus, we can’t call getInterestRate because it is defined in the GoldAccount class. However, through dynamic binding, the “correct” endOfMonth is called, depending on the actual instance type.

An array of type GoldAccount can only hold GoldAccount objects (and any subclass of GoldAccount); however, it cannot hold BasicAcocunt object because a BasicAccount is-not-a GoldAccount .

10

Page 11: mypages.valdosta.edu · Web viewCS 1302 – Chapter 11. Inheritance & Polymorphism. Reference Sections 11.1-11.15. 11.1 – Introduction. Suppose we have the . Dog . class …

2. The fact that an array defined with a super-type can contain items of that class or any subclass provides for an easy implementation of the 1-to-many relationship. Consider the classes below (Note that the BasicAccount is slightly different than the one considered earlier. The earlier one had an endOfMonth method that was overridden in GoldAccount. In this example, there is an applyInterest method that is overridden).

Note the following about the classes above:

A Person can have many accounts and the accounts themselves can be of various types. For example:

None of the methods in the Person class depends on any of the subclasses (look at the types for the parameters for the methods and the return types); they only depend on BasicAccountThis means that we can add new subclasses and not have to modify the Person class.

The subclasses can override whichever methods they need too. For example, see the withdraw method; perhaps a BasicAccount gets 3 withdrawals before there is a charge, and GoldAccount gets 5. The PlatinumAccount inherits the withdraw method from GoldAccount, so it gets 5 also. The StudentAccount inherits withdraw from BasicAccount. The applyInterest method is similar, it can be implemented differently in subclasses.

The account class hierarchy is extensible, meaning we can add new classes without breaking the Person class.

11

Page 12: mypages.valdosta.edu · Web viewCS 1302 – Chapter 11. Inheritance & Polymorphism. Reference Sections 11.1-11.15. 11.1 – Introduction. Suppose we have the . Dog . class …

3. Let’s look carefully at some of the methods in the Person class. The complete code is found in Appendix 1.

a. The addAccount method uses a super-type reference (BasicAccount) to define its parameter.

public void addAccount(BasicAccount a) {if(numAccounts<accounts.length) {

accounts[numAccounts++] = a;}

}

This means that the method can accept any kind of account:

Person p = new Person("Lenze");BasicAccount ba = new BasicAccount(1900.0);GoldAccount ga1 = new GoldAccount(500.0, 0.1);

p.addAccount(ba);p.addAccount(ga1);

b. The getAccount method uses a super-type reference (BasicAccount) to define its return type:

public BasicAccount getAccount(int i) {if( i>=0 && i<numAccounts) {

return accounts[i];}return null;

}

Thus, we can retrieve the second account with:

BasicAccount ba2 = p.getAccount(1);

Note that although the second account added above is in fact a GoldAccount, we can not refer to it as that. For example, this will not compile because the return type for the method is BasicAccount:

GoldAccount ga3 = p.getAccount(1);

We will see soon how we can “convert” it to a GoldAccount through a process called casting.

c. The applyInterest method loops through the accounts and calls applyInterest on each one (delegation) and the actual applyInterest method that is called depends on the actual type of the instance (dynamic binding):

public void applyInterest() {for(int i=0; i<numAccounts; i++)

accounts[i].applyInterest();}

12

Page 13: mypages.valdosta.edu · Web viewCS 1302 – Chapter 11. Inheritance & Polymorphism. Reference Sections 11.1-11.15. 11.1 – Introduction. Suppose we have the . Dog . class …

4. The addAccounts method accepts an array of BasicAccounts. An array of that type or any sub-type can be passed as an argument. For example:

public void addAccounts(BasicAccount[] accounts) {for(BasicAccount a : accounts) {

addAccount(a);}

}

An array of BasicAccount:

Person p = new Person("Nate");BasicAccount ba = new BasicAccount(1900.0);GoldAccount ga1 = new GoldAccount(500.0, 0.1);GoldAccount ga2 = new GoldAccount(2300.0, 0.1);

BasicAccount[] bAcnts = {ba,ga1,ga2};

p.addAccounts(bAcnts);

An array of GoldAccount:

GoldAccount ga3 = new GoldAccount(1500.0, 0.07);GoldAccount ga4 = new GoldAccount(2000.0, 0.09);GoldAccount[] gAcnts = {ga3,ga4};

p.addAccounts(gAcnts);

Homework:

2. Continuing from problem 1, write a Warehouse class that can contain up to 20 Skus. You should provide methods to: add a Sku, remove a Sku, get the total cost of all the Skus, add an array of Skus. You should also write a test class. Note, the remove method will take some thought. When you remove at a particular index, you must move everything to the right of the removed element back one position to the left. For example, suppose the skus array contains these elements:

Then, warehouse.removeSku(3) results in:

You don’t necessarily need to set the element at position 5 to null. It can still have a reference to socks; however, it can’t be accessed because numSkus=5.

13

Page 14: mypages.valdosta.edu · Web viewCS 1302 – Chapter 11. Inheritance & Polymorphism. Reference Sections 11.1-11.15. 11.1 – Introduction. Suppose we have the . Dog . class …

Section 11.8 – Casting

1. As shown below (and previously), we can have a BasicAccount reference to a GoldAccount instance. In addition, we can cast the instance to a GoldAccount reference (because it really is one).

2. Casting can fail. The code below compiles, but generates a run-time error when executed: ClassCastException. The reason is simple: A GoldAccount is-a BasicAcocunt, but a BasicAccount is-not-a GoldAccount.

So why does the code compile? A BasicAccount reference can refer to a GoldAccount instance (as shown in 1 above). Thus, the compiler does not know when you write this statement:

GoldAccount ga = (GoldAccount)ba;

The compiler doesn’t know the exact type of instance that ba refers to; that is only known at runtime.

3. The safe way to cast is to make sure the instance is really an instance of the class you want to cast to before casting. As shown below, Java’s instanceof operator takes a reference variable on the left and a class name on the right, returning true if the reference variable refers to an instance that really is an instance of the class name.

4. Consider the inheritance hierarchy shown on the right. Note the following:

a. A PlatinumAccount is-a GoldAccount and a BasicAccount.

BasicAccount pa = new PlatinumAccount(600.0, 0.1);

14

Page 15: mypages.valdosta.edu · Web viewCS 1302 – Chapter 11. Inheritance & Polymorphism. Reference Sections 11.1-11.15. 11.1 – Introduction. Suppose we have the . Dog . class …

System.out.println(pa instanceof GoldAccount); // trueSystem.out.println(pa instanceof BasicAccount); // true

b. A GoldAccount is-not-a StudentAccount. In other words, the code below prints false.

BasicAccount ga = new GoldAccount(200.0, 0.15);

System.out.println(ga instanceof StudentAccount); // false

5. Suppose we want to add a method to the Person class that returns the total of balances for all GoldAccounts:

public double getTotalGoldAccounts() {double sum = 0.0;for(BasicAccount a : accounts) {

if(a instanceof GoldAccount) {sum += a.getBalance();

}}return sum;

}

Note: No casting was necessary since we are not calling a method that is only defined in the GoldAccount.

This method will also include PlatinumAccounts (because a PlatinumAccount is-a GoldAccount). Thus, if we truly only wanted the sum balances of GoldAccounts, then we would need to exclude PlatinumAccounts:

if((a instanceof GoldAccount) && !(a instanceof PlatinumAccount)) {sum += a.getBalance();

}

6. Suppose we want to add a method to the Person class that returns the smallest interest rate for all GoldAccounts:

public double getSmallestInterestRate() {double smallestIntRate = Double.MAX_VALUE;for(BasicAccount a : accounts) {

if(a instanceof GoldAccount) {GoldAccount ga = (GoldAccount)a;if(ga.getInterestRate()<smallestIntRate) {

smallestIntRate = ga.getInterestRate();}

}}return smallestIntRate;

}

Note that we do have to cast because we are calling getInterestRate which is only defined in the GoldAccount.

15

Page 16: mypages.valdosta.edu · Web viewCS 1302 – Chapter 11. Inheritance & Polymorphism. Reference Sections 11.1-11.15. 11.1 – Introduction. Suppose we have the . Dog . class …

7. Suppose we want to add a method to the Person class that returns a GoldAccount array of only the GoldAccounts. Note that this method must first count how many GoldAccounts there are so that we can create the array of the proper size. We will implement this with a helper method.

private int getNumGoldAccounts() {int numGold = 0;for(BasicAccount a : accounts) {

if(a instanceof GoldAccount) {numGold++;

}}return numGold;

}

Then, we call this method to create the array of the proper size:

public GoldAccount[] getGoldAccounts() {GoldAccount[] gAcnts = new GoldAccount[getNumGoldAccounts()];int i=0;for(BasicAccount a : accounts) {

if(a instanceof GoldAccount) {gAcnts[i++] = (GoldAccount)a;

}}return gAcnts;

}

Note: We have to introduce a variable, i to keep track of the index of the current GoldAccount. We must cast a to be referred to as a GoldAccount in order to put it in the gAcnts array (because the

array only holds GoldAccounts)

Finally, we can call this method like this:

GoldAccount[] gAccounts = p.getGoldAccounts();

Homework:

3. Continuing from the previous problem, add the following methods to the Warehouse class:

a. Get the total cost of all RefrigeratedSkus.b. Get the average temperature of all RefrigeratedSkus.c. Return a RefrigeratedSku array that contains all the RefrigeratedSkus.

Also, write a test class and test methods to test these methods.

16

Page 17: mypages.valdosta.edu · Web viewCS 1302 – Chapter 11. Inheritance & Polymorphism. Reference Sections 11.1-11.15. 11.1 – Introduction. Suppose we have the . Dog . class …

Section 11.9 – Using the super Keyword & Constructor Chaining

Section 11.9.1 – More on Constructors

1. If a class does not explicitly call a superclass constructor then the compiler inserts a call to the superclass no-arg constructor. In other words, the compiler inserts, super() as the first statement of any constructor that does not explicitly call a superclass constructor. Thus, the two constructors below are identical:

public SuperBlob() {super();strength=10;

}

public SuperBlob() {strength=10;

}

2. Example – Note below (on left) that class B’s constructor does not explicitly call A‘s constructor; however, A’s no-arg constructor is implicitly called.

The output is:

AB

The code on the left is identical to this code:

class B extends A {public B( int x ) {

super();System.out.println("B");

} }

3. Example – The example on the left below will not compile. Notice that B’s constructor does not explicitly call A’s constructor. Thus, super() is inserted; however, there is no no-arg constructor in A. The compiler detects this and will not compile. The error message is a bit cryptic, so learn to recognize it:

error: constructor A in class A cannot be applied to given types;

Incorrect: Correctclass A { public A( int x ) { System.out.println("A"); }}

class B extends A { public B( int x ) { System.out.println("B"); } }

class A { public A() {} public A( int x ) { System.out.println("A"); }}

class B extends A { public B( int x ) { System.out.println("B"); } }

17

Page 18: mypages.valdosta.edu · Web viewCS 1302 – Chapter 11. Inheritance & Polymorphism. Reference Sections 11.1-11.15. 11.1 – Introduction. Suppose we have the . Dog . class …

Section 11.9.2 – Calling Superclass Constructors (Review)

1. A subclass can explicitly call an immediate superclass constructor with the use of:

super( argList );

which must be the first statement of the constructor. Any other initialization would occur after the call to super.

2. Example – Suppose a Dog class has a constructor that takes a name. Next, suppose WolfDog is a subclass that introduces a toughness, which, along with the name is accepted in its constructor. Thus, the WolfDog’s constructor should call the Dog’s constructor and when the Dog’s constructor finishes control returns to the WolfDog’s constructor as shown below.

Section 11.9.3 – Constructor Chaining

1. A constructor can do one of three things:

a. Call another constructor in the same class with: this( argList )b. Call a constructor in the immediate superclass with: super( argList )c. Implicitly call the no-arg constructor in the immediate superclass.

Thus, constructors can be chained together.

2. Rules of Constructor Chaining in Java:

this() or super() must be the first statement in the constructor. We can not use this() and super() in a same constructor, because both must be a first statement in the

constructor and that is not possible. We cannot add this() in all the constructors of a same class, there should be at least one constructor

without this() statement. If you did not add this() or super() in a constructor then Java compiler implicitly add super() statement in

the constructor that will call immediate super class default or no- argument constructor. The constructor invocation and execution happens exactly opposite, means if we called the constructors

in 1, 2, 3 order then the execution will be in 3, 2, 1 order.18

Page 19: mypages.valdosta.edu · Web viewCS 1302 – Chapter 11. Inheritance & Polymorphism. Reference Sections 11.1-11.15. 11.1 – Introduction. Suppose we have the . Dog . class …

3. A constructor’s purpose is to define the initial state of an object (and possibly do some preliminary tasks). It does this by assigning sensible values to the instance variables. When possible, the instance variables should only be assigned a value in one constructor. The other constructors should call this constructor using this or super.

4. Example – Write the Dog and WolfDog classes as described below:

A Dog can be created in two ways:

With a name argument With no argument. In this case the name is set

to “undefined”

A WolfDog also has a toughness property. A WolfDog can be created in three ways:

With a name argument in which case toughness is initialized to 1.0

With name and toughness arguments With no argument, in which case toughness is

initialized to 1.0

A class diagram is shown on the left. Study the code below carefully to see how the various constructors call one another:

19

Page 20: mypages.valdosta.edu · Web viewCS 1302 – Chapter 11. Inheritance & Polymorphism. Reference Sections 11.1-11.15. 11.1 – Introduction. Suppose we have the . Dog . class …

5. Examples – Three examples of constructor chaining are below. On a test you may have a question like these where you are asked to display the output.

a. Example – Consider the classes A and B shown on the right and the sample code to create a B object. What is the output? Consider the numbered steps:

1. B’s constructor that accepts a char is called

2. which calls the no-arg constructor in B3. which implicitly calls A’s no-arg

constructor4. which prints “M” then returns to B’s

no-arg constructor and prints “Z”5. then returns to B’s constructor that

accepts a char and prints “T”. When this finishes the B object has been created.

b. Example – Consider the classes A and B below and the sample code to create a B object. What is the output?

Output:1234

20

Page 21: mypages.valdosta.edu · Web viewCS 1302 – Chapter 11. Inheritance & Polymorphism. Reference Sections 11.1-11.15. 11.1 – Introduction. Suppose we have the . Dog . class …

c. Example – Consider the classes A and B below (same as above) and the sample code on the right. What is the output?

Classes: Sample Code:B b1 = new B(9);B b2 = new B("s");

Output:123

12

class A { public A() { System.out.println("1"); } public A( int x ) { this(); System.out.println("2"); }}

class B extends A { public B() { this( 77 ); System.out.println("4"); } public B( int x ) { super( x ); System.out.println("3"); } public B( String s ) { System.out.println("2"); }}

Homework:

4. Consider problem 1. Modify the code from problem 1 so that a RefrigeratedSku has an additional constructor that just accepts the weight and in this case sets the temperature to 40.0 degrees. Similarly, add an additional constructor to the FrozenSku that just accepts the weight and in this case sets the temperature to 30.0 degrees. Write code to test.

5. Consider the classes below

class BasicAccount { private double balance; private String name;}

class SavingsAccount extends BasicAccount { private double interestRate;}

A BasicAccount can be created by supplying either (a) a name or (b) a name and a balance. A SavingsAccount can be created by supplying either (a) a name and an interest rate or (b) a name, balance, and interest rate. Write the required constructors. If the balance or interest rate is not supplied then they should be set to 0.0.

21

Page 22: mypages.valdosta.edu · Web viewCS 1302 – Chapter 11. Inheritance & Polymorphism. Reference Sections 11.1-11.15. 11.1 – Introduction. Suppose we have the . Dog . class …

Section 11.10 – Calling Superclass Methods

1. You can call any public superclass method by simply invoking the method, or you can precede the call with super. For example:

super.method( argList );

We normally don’t do that, we simply call the method as we would any method that exists in a class.

However, sometimes you want a subclass to call an overridden (superclass) method. An example is shown on the right. You would want to do this if the superclass method provided some functionality that you need in the subclass overridden method. Occasionally I find use for this when a superclass toString method returns the state and the subclass overrides toString to provide exactly the same information as the superclass toString, but then tacks on the additional state of the subclass.2. Example – Override the bark method in WolfDog, but call the superclass bark method:

Dog – Superclass WolfDog - Subclasspublic class Dog {

private String name;public String getName() {

return name;}public void setName(String

name) {this.name = name;

}

public String bark() {return "bark";

}}

public class WolfDog extends Dog {public String bark() {

String msg = super.bark();return msg + " BARK";

}}

Section 11.11 – Preventing Extending and Overriding

1. To prevent a class from being subclassed (extended) declare it final.

public final class Person { . . .}

2. To prevent a method from being overridden declare it final.

public final void bark(){ ...}

3. A field can be declared final in which case it is a constant and can never be changed.

class Dog { public final String name = "Snoopy"; . . .

22

public void method() {...super.method();

...}

Page 23: mypages.valdosta.edu · Web viewCS 1302 – Chapter 11. Inheritance & Polymorphism. Reference Sections 11.1-11.15. 11.1 – Introduction. Suppose we have the . Dog . class …

}

Section 11.9 – OO Modelling

1. You should only use an inheritance relationship when “is-a” makes sense. For example, these would satisfy is-a:

A Person and a Dog both have a name, walk, and run, but a Person is not a Dog. Thus, we would not let a Dog class extend a Person class (or visa-versa).

2. However, just satisfying the is-a relationship is not enough to use inheritance. For example, the situation on the right would not be a good use of inheritance. To use inheritance properly, there should be at least one behavior that is implemented differently. The example on the right satisfies is-a, but if there were no behavior that is different, it could be better modeled by simply adding a courseName attribute to the Course class and then you could have instances that have different values for this attribute as shown below.

3. We can define a multilevel hierarchy as long as it follows the is-a rule.

23

Page 24: mypages.valdosta.edu · Web viewCS 1302 – Chapter 11. Inheritance & Polymorphism. Reference Sections 11.1-11.15. 11.1 – Introduction. Suppose we have the . Dog . class …

4. Java allows only single inheritance, that is, a class can only extend one superclass. Some languages (C++, Python) allow multiple inheritance where a class can extend several superclasses. For example, the situation on the right is not allowed in Java.

Appendix – Review of Polymorphism & Dynamic Binding

The following is a review of polymorphism and dynamic binding.

1. Consider the class diagram shown on the right that will be used in the notes for this section. There, we see the subclass WolfDog inherits getName and bark, and introduces howl.

2. As a review, consider the terminology shown in the figure below. We say that we are using a WolfDog reference (wd) to refer to a WolfDog instance.

3. Java allows us to use a supertype reference to refer to a subtype instance. Thus, we can use a Dog reference type to refer to a WolfDog instance:

The variable d is referred to as a supertype reference. It is also called a polymorphic reference because d can refer to different types of Dogs.

4. The reason we can do this (rather loosely) is that a WolfDog is-a Dog. Anything you can do with a Dog, you can do with a WolfDog. However, the converse is not true: a Dog is not a WolfDog. In Java you can always refer to a subclass instance (WolfDog) with a super-type reference (Dog). Now, why we would want to do this is a bit more challenging to understand. There are tremendous benefits which we will discuss throughout the remainder of the course!

5. Polymorphism means that a variable of a supertype can refer to a subtype object.

6. When we use a supertype reference we can only use the members that are defined in the supertype. In other words, if the instance is a subtype, we can’t use members that are defined in the subclass but not in the superclass.

7. Example:

Dog d = new WolfDog("Leo");

24

Page 25: mypages.valdosta.edu · Web viewCS 1302 – Chapter 11. Inheritance & Polymorphism. Reference Sections 11.1-11.15. 11.1 – Introduction. Suppose we have the . Dog . class …

the actual instance is a WolfDog, but it is being referred to as a Dog. Thus, we can call:

d.bark();d.getName();

25

Page 26: mypages.valdosta.edu · Web viewCS 1302 – Chapter 11. Inheritance & Polymorphism. Reference Sections 11.1-11.15. 11.1 – Introduction. Suppose we have the . Dog . class …

However, we cannot call the howl method. This code will not compile:

d.howl();

Again, even though the instance is a WolfDog, it is being viewed through a supertype reference, Dog. The Dog reference only allows access to the methods defined in the Dog class: getName and bark.

8. I think of it this way: the reference type is a lens through which you can view the instance. The lens belongs to the reference (superclass), not the instance. Thus, the only thing you can see through the lens is the public (and sometimes protected and unspecified) members defined by the reference type, not the instance. The instance may have other behaviors, but the lens can’t see them. We can assign a subclass instance to a supertype, but the reference cannot see any behaviors that the subclass may have defined. To access those, we must use a reference with the subtype.

9. In Java you can always pass a subclass instance to a method that defines a parameter defined as a supertype. This is also referred to as polymorphism. This is very useful because a method written with a supertype parameter can be used with an subclass instance, even ones that haven’t be written yet.

10. Example – Suppose the Dog class provides the method shown on the right where a Dog can barkAt another Dog. Define some dogs:

Dog d1 = new Dog("Snoopy");Dog d2 = new Dog("GiGi");WolfDog wd1 = new WolfDog("Juno");Dog wd2 = new WolfDog("Zoro");

Then, we can call the barkAt method with any combination of dogs and wolfdogs.

d1.barkAt(d2);d1.barkAt(wd1);wd1.barkAt(d1);wd1.barkAt(wd2);

In other words, we can pass a WolfDog instance as an argument to the barkAt method which accepts a Dog.

26

public String barkAt(Dog d) {return this.getName() +

" barks at " + d.getName();

}

Page 27: mypages.valdosta.edu · Web viewCS 1302 – Chapter 11. Inheritance & Polymorphism. Reference Sections 11.1-11.15. 11.1 – Introduction. Suppose we have the . Dog . class …

11. Example – Consider the classes defined on the left and the static methods on the right.

class A { public String toString() {

return "A"; }}

class B extends A { public String toString() {

return "B"; }

}

class C extends B {}

public static void m( A a ) { System.out.println( a );

}

public static void m2( C c ) { System.out.println( c );

}

State whether the method calls below will: (a) compile, (b) generate a run-time error, or (c) what output will it produce?

a. m( new A() );b. m( new B() );c. m( new C() );

d. m2( new C() );e. m2( new B() );

Homework

6. Define these terms in your own words:

a. Reference typeb. Supertype reference (or polymorphic reference)c. Polymorphism

7. True or False

a. You can always refer to a supertype instance with a subtype reference.b. You can always refer to a subtype instance with a supertype reference.c. You can always pass an instance of a subclass to a method with a parameter defined as a supertype.d. You can sometimes pass an instance of a superclass to a parameter defined as a subclass.

8. Define dynamic binding in your own words.9. True or False

a. An instance that is referenced by a supertype can call any methods on that instance as long as they are defined in the supertype.

b. An instance that is referenced by a supertype can call any methods on that instance, even ones that are not defined supertype as long as they are defined in the subclass.

27

Page 28: mypages.valdosta.edu · Web viewCS 1302 – Chapter 11. Inheritance & Polymorphism. Reference Sections 11.1-11.15. 11.1 – Introduction. Suppose we have the . Dog . class …

8. Consider the class hierarchy shown on the left, below. Thus, if a variable has a reference type of W, we can use it to hold references to an instance of W or any of its descendants (classes that extend W), X, Y, or Z, as shown in the figure below.

Class Diagram Relationships References

an X is-a W a Y is-a W a Z is-a X a Z is-a W.

But an X is not a Y an X is not a Z a Z is not a Y

W w = new W();X x = new X();Y y = new Y();Z z = new Z();

Valid: w=x; w=y; w=z;x=z;

Invalid: x=w; x=y;y=z;

28


Recommended