(syllabus and calendar)
Ch. 7 Inheritance
|
Session 7Inheritance and the keyword extends Using super to access superclass members super() to call constructor of the superclass multilevel hierarchy: C extends B, B extends A constructors and private members are not inherited Enforcing inheritence by a call to the constructor of the superclass Recreating super() if the default constructor is removed - parameterless constructors Constructor should not call a method that a subclass can override Superclass reference to subclass object
Abstract Class and method overriding Subclassing an abstract class to encapsulate specialization Inheritence from most immediate superclass final keyword has three levels (variable, method, class) Superclass array can store subclass objects |
In this example, the main method contains only one line of code: to instantiate an object
of type C.
What is the output of ABC.java?
We see in ABCWithCast.java on line 25 that a subclass can be cast to a superclass, but a superclass cannot be cast to a subclass:
Casting to a superclass type is allowed, but casting to a subclass type is not
allowed.
An analogy: Michelle Robinson Obama is of type Robinson through her father,
Frazier Robinson, but we cannot say that Frazier Robinson is of type Obama.
Michelle inherited DNA from Frazier, but Frazier has no DNA from Michelle.
To better understand the purpose of the order of construction, let's add some fields (see ABCFields.java):
Summary: The order of construction implicitly calls the superclass constructor to enforce the inheritance of methods and fields, and to enforce the initialization of subclass fields to superclass field values.
So we can say that inheritance is a construction, even a super construction.
We might think of a subclass as looking up to its superclass so as to receive its inheritance. The Unified Modeling Language diagram shows the subclasses looking up to their single parent class.
A subclass inherits the fields and methods of its superclass:
How about this example?
- a class cannot be subclassed ("extend" will block compilation of the attempted subclass),
which prevents the methods from being overridden- a method cannot be overridden (subclasses cannot declare this method name)
- a variable cannot be reassigned to a different value (it is a constant) from its original "initialized" value.
For example, a declaration of a String variable defaults to null,
and a declaration of a boolean variable defaults to false.
Such variables can be assigned a value exactly one time.
final int BOILING_POINT = 100; cannot be reassigned to 212
// illegal
BOILING_POINT = 212;SUMMARY: java.lang.String is a final class - see http://docs.oracle.com/javase/7/docs/api/java/lang/String.html - which means no application can change the fields or methods of the String class. This provides reliable behavior.
A final class cannot be subclassed.
A final method cannot be overridden by a subclass.
However, if the signatures differ, a subclass can have a method with the same name as a final method of its superclass.
To create a "constant" field, use the keyword final. A common use case is for setting and safeguarding the value of an error message.
A medical school trains students to be either a physician or a surgeon. In this sense, the Doctor superclass has two subclasses, Physician and Surgeon. A surgeon is a handyman or hand-worker (chiral + ergon = kheirourgia), and historically, emerged from the profession of the barbershop. In the Middle Ages, barber-surgeons had the periodic double duty of shaving monks and draining their blood, both of which they learned without going to the university. The barber-surgeons also accompanied soldiers to battlefields both to cut soldiers' hair and amputate legs, if necessary. http://en.wikipedia.org/wiki/Barber_surgeon#Middle_Ages_in_Europe.
A physician comes from a different tradition, a university-trained profession, that uses drugs instead of knives - http://en.wikipedia.org/wiki/American_College_of_Physicians. Medicine uses scientific research more than surgery does, hence the serpent of wisdom in the logo of both the pharmacy and the physician.
However, nowadays it is convenient to consider both of them to be doctors, even though a student must still declare a desire to specialize before graduation in either medicine or surgery. In this sense, Doctor is an abstract class that represents either an instance of Physician or an instance of Surgeon.
A subclass is an extension or specialization. For example, an instance of BrainSurgeon of a specialized class of Doctor.
The keyword extends allows you to declare that a class is a specialization (subclass) of another class, its superclass. For example, a medical doctor might consider herself or himself to be a special kind of person.
class Person
{
String name = "";
int ssn = 0;
Person(String name)
{
this.name = name;
}
Person(int ssn)
{
this.ssn = ssn;
}
}
class Doctor extends Person
{
Doctor(String name)
{
super(name);
}
Doctor(int socialSecurityNumber)
{
super(socialSecurityNumber);
}
}
class PersonDemo
{
public static void main(String[] args)
{
Doctor drwatson = new Doctor("Watson");
drwatson.ssn = 001331234;
System.out.println(drwatson.name + ": " +
drwatson.ssn);
Doctor drpepper = new Doctor(823556789);
drpepper.name = "Soft Drink";
System.out.println(drpepper.name + ": " +
drpepper.ssn);
}
}
We have seen multiple classes in the same compilation unit (file). Any number of class can be in the same java file, but it is generally a good idea to have only one. If the file has the main class, the file name must match the class with main.
Note: We can also put each class in each own file, as long as the class with main can see the other classes. Currently, we use the default package, so any class in the current directory is visible.
When you compile the class with main, the compiler also compiles any classes that main references.
Here, when we compile the class with main, we generate three class files. In our domain logic, the Triangle and the Rectangle classes are specializations of TwoDShape. The subclasses have special ways of calculating area.
Subclasses inherit from their single-inheritance superclass. The superclass encapsulates the general logic. The subclass adds specialization.
CelloCake extends BirthdayCake
DrippingIcingBlackAndWhiteCake extends WeddingCake
Both cakes have the same basic ingredients. In the .NET vocubulary, the superclass is called the "base" class. The difference is the added (or subtracted) extras, such as bells and whistles, external writing, and colorful props.
The following examples of subclasses are special types for special use cases:
Thus, we can re-use shared, general code and only have to write the specialized differences (the deltas) on the subclasses. Inheritance supports the maximum appropriate code reuse. This accelerates development and streamlines quality assurance. Therefore, even though Java bytecode executes more slowly than C native code at runtime:
In the following example, Line 29 must be commented out, even though lines 23 and 14 are allowed. This means that the subclass did not inherit the constructor that takes a boolean argument.
The file named ConstructorInheritanceDefaultLost.java does not compile. Why not?
Because the custom constructor that is declared on line 3 automatically removes the default constructor. Therefore, the superclass no longer has a parameterless constructor. Line 12 is calling a non-existent constructor.
Otherwise the keyword private would not
prevent another programmer from subclassing a class to gain access to the
private members.
(A biblical analogy might be Genesis 9:20, where Noah's son, Ham, is not
allowed to see the private members of his father.
As punishment
therefore, Noah makes Ham inherit a curse that is the South claimed justified
the War of Succession -
http://en.wikipedia.org/wiki/Curse_of_Ham.
In this example, the width and height of the private member is not visible to the children classes.
Info for t1:
Triangle is isosceles
Width and height are 4.0 and 4.0
Area is 8.0
Info for t2:
Triangle is right
Width and height are 8.0 and 12.0
Area is 48.0
Now let's set values with the constructor of the subclass instead of doing so in the class with main.
Info for t1:
Triangle is isosceles
Width and height are 4.0 and 4.0
Area is 8.0
Info for t2:
Triangle is right
Width and height are 8.0 and 12.0
Area is 48.0
Here, we add a constructor to the superclass, which can update functionality
that subclasses do not know about.
Notes:
The following examples uses accessor methods, which are also called "getter" methods, while the "setter" methods are mutators (see also http://en.wikipedia.org/wiki/Mutator_method).
Info for t1:
Triangle is isosceles
Width and height are 4.0 and 4.0
Area is 8.0
Info for t2:
Triangle is right
Width and height are 8.0 and 12.0
Area is 48.0
If your method hides one of its superclass's member variables (by having
the same name), your method
can refer to the hidden variable through the use of the super
keyword. Similarly, if your method overrides one of its superclass's methods
(by having the same name and signature),
your method can invoke the superclass version of the overridden method through the use of the
super
keyword. (Compare to how a local variable name can hide a
instance variable name, or how a formal parameter name can hide a field name,
which is unhidden by this.fieldName.)
In which line does the subclass hide a variable of the superclass?
In which line does the subclass override a method of the superclass?
Here, the subclass makes separate calls to each of the superclass constructors. The syntax for calling a superclass constructor is super(parameter_list). We care about the parameter list, the signature, when calling a constructor because a constructor, like a method, can be overloaded.
Info for t1:
Triangle is right
Width and height are 8.0 and 12.0
Area is 48.0
Info for t2:
Triangle is right
Width and height are 8.0 and 12.0
Area is 48.0
Info for t3:
Triangle is isosceles
Width and height are 4.0 and 4.0
Area is 8.0
Using super to access an instance variable of the superclass. Remember, the superclass does not know about its subclasses. Therefore, the changes made on the inherited member do not affect the copy of that member in the superclass. Here, we use super.superclass_member in a manner analogous to using this.class_member, that is, to unhide a instance variable that has been hidden by a local variable. Otherwise, from B's point of view, the variable i refers to this.i, that is, B's version of i.
Let's review with a different class hierarchy.
Semi can carry 44000 pounds.
To go 252 miles semi needs 36.0 gallons of fuel.
Pickup can carry 2000 pounds.
To go 252 miles pickup needs 16.8 gallons of fuel.
There is no limit to the number of levels in a hierarchy of inheritance. (Japheth to Jefferson Davis, or Ham to Frederick Douglas, might be 150 generations.)
Here, we extend TwoDShape with Triangle, and also design a specialize triangle, ColorTriangle. This is for purposes of illustration because color should be an attribute, property, or field of Triangle or TwoDShape.
Info for t1:
Triangle is right
Width and height are 8.0 and 12.0
Color is Blue
Area is 48.0
Info for t2:
Triangle is isosceles
Width and height are 2.0 and 2.0
Color is Red
Area is 2.
The order of construction is determined by derivation. Java enforces that the superclass has priority.
If the superclass has instance variables that the constructor initializes, we can be certain that the subclass that inherits these instance variables will inherit them with the proper initialization.
This example use this.methodName() and super.methodName() to make use of method overrides.
If any constructor is defined, the default constructor disappears, and only an explicit constructor can have the empty parameter list.
Because Java automatically calls the default constructor, both the superclass and the subclass MUST have the default constructor or something that looks like the default constructor, that is, a parameterless constructor.
If a constructor calls a method that a subclass can override, when the subclass constructor implicitly calls the superclass constructor, any non-static fields are considered to be not yet initialized. This is why some developer tools, such as NetBeans, do not allow you write such code. Solutions include making the method final or making the subclass field static.
The superclass X does not know about Y's field (instance variable) b. However, a subclass can assign a reference of its superclass. In other words, a superclass reference can refer to a subclass object. Can a subclass reference refer to a superclass object? No. Is this similar to the implicit cast of a primitive to a widening type?
The following program has a subclass that passes an object of its type to the superclass constructor. This supports basic code reuse. Insofar as the subclass extends the superclass, the subclass is of the type of the superclass. (A BrainSurgeon is also a Doctor is also a Person.) Is there a relationship between lines 64 and 22?
Info for t1:
Triangle is right
Width and height are 8.0 and 12.0
Area is 48.0
Info for t2:
Triangle is right
Width and height are 8.0 and 12.0
Area is 48.0
A reference of the superclass can be assigned to a reference of a subclass (line 40), but it has access only to the members that the superclass knows about. In this case, the superclass Book does not know about the subclass having a specialized field.
The output is:
constructor for the superclass that takes no arg
constructor for the superclass takes a book object
superclass book title
constructor for the superclass that takes no arg
superclass book title
subclass book title
assigning a superclass reference variable to a subclass object reference
Although the reference is of type Book, the object is of type MusicBook: MusicBo
ok@19821f
inherited methods and fields remain available:
superclass book title
However, the subclass methods and fields are NOT available to a reference of the
superclass type
Summary: Overloading is HORIZONTAL typically within the same class, and means different
signatures for the same method name.
O
v
e
r
r
i
d
e
Overriding is VERTICAL - how a subclass customizes the behavior it inherits, and means the
same method signature but different implementation code.
All mammals have an eat method. The horse overrides this inherited method by
chomping on dry hay in a circular motion with teeth that never stop growing (and
being grinded down). The cowboy overrides the eat
method by shoving campfire beans with a fork down what might be a toothless
mouth.
In this photo, the cowboy's goWhereIWantToGo()
method overrides the horses goWhereIWantToGo()method.
The overridding method is in the superclass. The
overridden method is in the subclass.
Chomping on dry hay and eating campfire beans with the fork are specializations of the general method of eating. The Horse class eat() method overrides the Mammal class eat() method, just as the Cowboy class eat() method overrides the Mammal class eat() method.
These photos show the Cowboy and the Horse can both be viewed as overriding a Mammal.
Whereas method overloading is within the same class (horizontal), method
overriding means the subclass method overrides the superclass method (vertical)
it inherits.
Method overloading is polymorphism; method overriding is an exception to
inheritance.
SUMMARY: Whereas overloading does not consider the return type (and constructors do not have a return type), overriding is solely for methods, and the return type must match, as well as the method name and the parameter list.
Suppose you are the programmer who must write a subclass for a superclass. You see that one of the methods the subclass inherits from the superclass must have different behavior. A use case (http://en.wikipedia.org/wiki/Use_case) might be the calculateTax() method, which is different depending on the local nation, state, county, and/or city. Some localities have only national tax, others have both federal and state, still others have federal, state, and city.
The following example illustrates overriding the inherited show() method.
The following demonstrates a method overloading. Do the signatures of the show method match?
To override a method, the subclass
version must have the identical signature as the
superclass
version.
Otherwise, we have
overloading
that happens to occur in the class that inherited the method.
So, in a sense, overloading,
which is normally horizontal, can be vertical: the subclass can introduce a
different signature to the method it inherits.
Overriding is always vertical.
At runtime, Java can determine which version of method to run according to which object that method is on.
Method overriding can be used with the best practice of moving common logic up to the superclass. Shapes have areas, but each subclass can override the area method for its special circumstances. What are the contents of the array created in line 127? Does it violate the rule that an array must collect objects of solely ONE type?
object is triangle
Area is 48.0
object is rectangle
Area is 100.0
object is rectangle
Area is 40.0
object is triangle
Area is 24.5
object is generic
area() must be overridden
Area is 0.0
Suppose you can provide some functionality to other programmers, but you know they will need to add more functionality. For example, suppose you can encapsulate the logic for a stream of data, but other programmers will need to implement how that data works in different situations. In the java.io.package, InputStream is an abstract class, http://docs.oracle.com/javase/7/docs/api/java/io/InputStream.html, that has subclasses for everything from an audio input stream, http://docs.oracle.com/javase/7/docs/api/javax/sound/sampled/AudioInputStream.html, to a file input stream, http://docs.oracle.com/javase/7/docs/api/java/io/FileInputStream.html.
SUMMARY: If a class is declared abstract:
The syntax involves putting the keyword abstract at the beginning of the class declaration:
abstract class className
{
// zero or more methods can be declared abstract
abstract methodName(parameterType
parameterIdentifier);
}
An abstract class is similar to an ordinary class, as is its own type, but functions as a template for creating subclasses. An abstract class enforces an architecture contract that a subclass implementation act as if it were overriding a method. However, the subclass is actually implementing a method specification.
Think of an abstract class as a starter kit.Right "out-of-the-box", you have
some implemented functionality, but you might want to add more functionality on
your own.
In the analogy with the recreation vehicle accessory starter kit, you might have a second electrical adapter that works with European outlets that are 220 volts instead of 110 volts. Or you might want gloves and deodorizers that are stronger than those originally provided.
Shifting to electrical engineering, this board provides chips that provide a system clock and power to light the LEDs, but allows you to add your own control software as well as an optional LCD display module.
For example, you could add an LCD display module that displays system
information, contact information for technical support, a touch screen to enter
a password, or a web browser for handy use with a microscope:
The following example prescribes that subclasses shall implement a getMaximumSpeed method, which the ModelT class does. The Tbird subclass of ModelT overrides that method, and uses the keywords super and this to access both the overridden version and the override version.
Use Case: In Java coding, you might provide an abstract class that has
implemented openDocument() and
closeDocument() methods, but an abstract method
for displayDocument(), because you do not know
the size of display device, which could small enough to fit on an earring or
large enough to see from across the Huong-Pu or Yang-zte River.
ThisAndSuperUsageDemo.java illustrates the use case of an abstract class supporting a design even though it is unable to know the technological possibilities and limitations of the customer-programmer.
An abstract class is similar to an ordinary class but functions as a template for creating subclasses. For example, the abstract class, java.io.InputStream http://java.sun.com/javase/6/docs/api/java/io/InputStream.html provides implementation methods for managing the bytes in an stream, such as read(byte[] b), mark(int readlimit), reset(), skip(long n), and close(). Therefore, subclasses, such as AudioInputStream and FileInputStream have the choice to reuse the superclass implementation or overwrite it, which is almost an "override" it.
Can I use the keyword abstract for a class that lacks an abstract method?
Let us prove that an abstract class cannot be instantiated. Will such code even compile?
AbstractDemoWithConcreteMethod.java shows that an abstract class is not required to have an abstract method, but you would only do this while you were developing the abstract methods.
A method can be abstract if it does not contain an implementation block, and if a method is abstract, the class must be declared abstract.
An abstract class cannot be instantiated. Instead, a subclass must fulfill the obligation to provide implementation, and only such a subclass can be instantiated:
Returning to the dynamic shapes solution, the DynShapes program included line 47, which is a hack insofar as:
Instead, we should declare the superclass to be an abstract class.
Every subclass that extends an abstract class inherits an obligation (we say a contract) to implement the abstract methods of the superclass.
This way, appropriate code is written where it is needed, and no code must be ignored.
An abstract class is a common solution when we know the subclass is likely to override the superclass.
In general, provide an abstract class when you can provide only SOME of the implementation, and other developers will later provide additional customization of your code. Use cases (http://en.wikipedia.org/wiki/Use_case) might be:
An abstract class cannot be instantiated, so a subclass does the instantiation. An abstract class can provide partial implementation. A non-abstract subclass typically overrides one or more methods of the abstract superclass. The non-abstract subclass can be instantiated.
Note:
This is shown in AbstractDemoWithConcreteMethod.java
Whether or not an abstract class is the superclass, the superclass should ALWAYS be more generic than its subclass. Therefore, we would not say that MontanaTax extends CaliforniaTax. Rather, each state tax extends a more generic, perhaps even abstract, superclass.
The output is:
Note: It seems my computer chip has an arithmetic error that is virtually insignificant.
A subclass inherits from its most immediate superclass the value of an
instantiated field.
A subclass also inherits from its most immediate superclass the behavior of an
overridden method.
See InheritMostImmediateDemo.java
The output is:
HybridSportsCarLuxuryModel is the same as its
superclass except the seats are mo
re comfortable.
myHybrid.numberOfWheels 4
myHybrid.numberOfPassengers 4
myHybrid.milesPerGallon 50
A hybrid uses both battery and gasoline.
myHybridSportsCar.numberOfWheels 4
myHybridSportsCar.numberOfPassengers 2
myHybridSportsCar.milesPerGallon 40
A hybrid uses both battery and gasoline.
myHybridSportsCarLuxuryModel.numberOfWheels 4
myHybridSportsCarLuxuryModel.numberOfPassengers 2
myHybridSportsCarLuxuryModel.milesPerGallon 40
A hybrid uses both battery and gasoline.
myElectricAutomobile.numberOfWheels 4
myElectricAutomobile.numberOfPassengers 4
myElectricAutomobile.milesPerGallon 9999
An electric uses no gasoline.
object is triangle
Area is 48.0
object is rectangle
Area is 100.0
object is rectangle
Area is 40.0
object is triangle
Area is 24.5
Write an abstract class called Animal that has at least one abstract method and one non-abstract method. Extend the abstract class in a non-abstract subclass that overrides the abstract method it inherits by implementing the abstract method. Your implementation must not be empty { }. In other words, provide code in the implementation code block, such as an indicative println method. Also override a non-abstract method it inherits.
Overriding: see
http://write-technical.com/126581/session7/index.htm#override
and
http://java.sun.com/docs/books/tutorial/java/IandI/override.html
Abstract class: see See http://write-technical.com/126581/session7/index.htm#Abstract%20Class
SUMMARY: A final class cannot be subclassed. A final method cannot be overridden. A final variable cannot be reassigned.
The keyword final has three levels of use in Java: variable, method, class.
Final can be used with a variable to make it a constant:
final int BOILING_POINT = 100;
The following example, FinalForErrorMessage.java, uses a standard convention for error messages. The API could advise user programmers to use the string constants. The associated integers can be changed between product releases without breaking code.
See FinalMethodDemo.java.
A method can be declared final. That means it cannot be overridden.
Use case example:
final void logonToServer(String password) { // do something }
prevents an override from changing the behavior of the logonToServer
method.
A class be declared final. That means that not only are its methods final, but the class cannot be extended by a subclass or even inherited by a subclass. A final class is one way to provide logic that is uniform throughout a large project involving many programmers. One use case is for an application to have one central Log of events for debugging.
Use case example: The architect ensures that everything related to the rules of the Authentication class remain intact by making Authentication a final class.
Making a class final is one way to attempt to ensure that no more than one instance of that class can exist. This approach is also known as the Singelton design pattern.
How can I create a class that is guaranteed to have only one instance? Such a class/object is known as a singleton. http://www.javaranch.com/newsletter/July2003/SaloonQnAOfTheMonth.html
An example of the singleton design pattern:
http://java.sun.com/docs/books/tutorial/java/nutsandbolts/finalVariables.html
A constant variable is a variable which is assigned a value once and cannot be changed afterward (during execution of the program). The compiler optimizes a constant for memory storage and performance.
Examples of constants
You can declare a variable in any scope to be final . The value of a final variable cannot change after it has been initialized. Such variables are similar to constants in other programming languages.
To declare a final variable, use the
final
keyword in the variable declaration before the type:final int aFinalVar = 0;The previous statement declares a final variable and initializes it, all at once. Subsequent attempts to assign a value to
aFinalVar
result in a compiler error. You may, if necessary, defer initialization of a final local variable by declaring the local variable and initializing it later:final int blankfinal; . . . blankfinal = 0;A final local variable that has been declared but not yet initialized is called a blank final.
A common use case for a final variable is a set of constants for error messages.
http://java.sun.com/docs/books/tutorial/java/javaOO/final.html
SUMMARY: A superclass array accepts objects its own type as well as objects of its specialized subclasses. However, a specialized array does not accept non-specialized objects.
Can the most specialized doctor attend a conference meant for ordinary doctors? Would an ordinary doctor be admitted to a conference specially designed for brain surgeons?
StoreStringAsTypeObject2.java shows that a superclass array can store an object of a subclass type.
However, if we reverse the situation, (see StoreStringAsTypeObjectReversed, which does not compile), we discover that a subclass array does not accept a superclass object.
Therefore, we can expect that an array of type Doctor will accept specialized doctors, but an assembly, of say, BrainSurgeon, will not accept an ordinary doctor.
SUMMARY: An array of objects can store any type of Object, be it an instance of String or any other subclass of java.lang.Object. An abstract class cannot be instantiated, so it cannot have objects to store in an array of objects. However, a subclass of an abstract class that, as subclass, is NOT abstract, can be the type of object stored in an object array, and array of the abstract class type, and an array of the its own class type (a subclass of the abstract class).
Consider AbstractArrayTypeDemo.java
AbstractArrayTypeDemo2.java shows that an array of an abstract class type can hold objects of its subclass.
When you are at the Object
level, you can only see that methods that belong to that class, such as
toString().
See
http://java.sun.com/javase/6/docs/api/java/lang/Object.html. The Object
class does not know anything about what a subclass might or might not have. If
you want to access the class members of a subclass, you have to work with that
subclass. To explicitly cast a object that is a subclass of
java.lang.Object to be considered as of type
java.lang.Object, you would use this syntax:
(Object) myObject;
Line 15 upcasts a String as an object. What is the use case for that? To select the a specific overload. See http://stackoverflow.com/questions/12843844/explicit-type-conversion-of-sub-class-object-to-super-class-in-java
void method(Object o) { }
void method(String s) { }
method("hello"); // calls method(String)
method((Object) "hello"); // calls method(Object)
a final class cannot be ________
a final method cannot be ________
a final variable cannot be ________
String[] myStringArray = new String[3];
Object myObject = new Object();
myStringArray[0] = myObject;