references: 'Just Java' P.V.Linden, 'Java Certification Study Guide', Heller&Roberts
Inheritance
Inheritence may be described variously as 1) extending 2) adopting 3)
adapting or 4) building
on a pre-defined parent class. In Java, if a parent is not explicitly
mentioned in the class definition
(after the extends keyword), the parent is Object implicitly.
The extends keyword, is followed
in a class definition by the parent or
superclass from which the new class is being defined
as inheriting from. Non-private, parent members are inherited
by the subclass as if they were
declared in the subclass. In Object-Oriented Programming, hierarchies
of classes are created
by class extensions. The hierarchies increase in specialization and
complexity proceeding from
top to bottom.
If you want a bilingual button, in java you don't have to re-invent
the button. In object-oriented
languages like java, you can inherit the attributes of an existing
button and then go on to add
your own features. The class extends the the parent class to become
the subclass.
A subclass is created using the extends keyword after the class
name and before the name
of the class that is being extended.
Example
class Child extends Parent
{ }
Subclassing JButton
/* by subclassing JButton, a custom button is obtained with a few lines of code without needing to rewrite or copy the hundreds of lines of code needed to build a functioning activatable visual component from scratch */ import javax.swing.*; class BiTextButton extends JButton{
class bT{
|
The inheritance, achieved by subclassing,
saves
on copying, modifying and
maintaining
code as well as ensuring compatibility with
future versions. Inheritance provides one of
the key objectives of object-oriented programming which is reusability.
Inheritance provides
more than a template for child classes. The parent class members may
be accessed by child
classes. So if a parent has a method, a child class can invoke it as
if it was it's own even though
it doesn't appear in the child's class definition. For example, in
the code above we call the
setText( ) method we inherit from the JButton class though we haven't
defined it in our child
version. By the same token JButton has parent classes and those parent's
members and
methods are also available for use in JButton and in our grandchild
class. There are a few
restrictions. Though descendants, subclasses cannot access parent members
marked private.
private carKeys; // a private variable in the parent class will not be accessible from the child class
A class may use member which it has inherited from anywhere in it's
parental hierarchy, all the
way back to Object (This
has practical implications when trying to trace a class member.When
looking in the API for say, a method or a static variable, if you don't
find it in the immediate
parent class, you may have to look higher up the hierarchy to locate
it.) The API lists inherited
features. // Check out a class
like JButton in the API and notice the lists of inherited methods etc.
More on Constructors
// for reference
/* Constructor Note: If you don't explicitly call the superclass constructor, the superclass no-args constructor is provided for you. If the superclass has no no-args constructor as a result of other constructors having been defined this automatic no-args constructor is not supplied. If you try to invoke it, it's not there and the compiler will report an error. super can be used to invoke the fields of any superclass. Run the following code, then comment out the no-args Bird constructor in the parent class. You'll get a compiler error indicating the absence of the no-args constructor the child class is trying to invoke. To summarize, if you define constructors, the automatic no-args constructor is not supplied. */ class Bird{
// the parent class with two constructors
class Parrot extends Bird{
// a child class invoking the two parent constructors
// constructing the parent and child via the childs two constructor forms class BirdBath{
|
" Is a " vs. " Has a "
To distinguish when a component should be a class member vs. an extension
of the
inheritance relationship, the " is a " / "
has a " test can be used.
Example 1 You
have a car class and an ID class : A car has
an ID OR A car is an ID
Has a is right so let ID be a member
of the car class.
Example 2
You have a mammal and dog class: A dog has a mammal
OR a dog is a
mammal A dog is a mammal so dog class
should extend mammal.
Java doesn't multiple inherit
The dilemna -->
If B & C descend from A, and D descends from B & C, given identical
variables, which does D inherit, B's or C's
The solution --> The
java interface type provides inheritance from several sources
without the complexity associated with multiple inheritance.
Variable Hiding
When a child class extends a parent class and then explicitly defines
identical variable to
those found in the parent, the child variables are said to hide or
mask the values of the
inherited parent variable. The parent values have still been inherited.
You just have to
take extra steps to expose these values. The following code example
will demonstrate this.
Code showing variable hiding of a parent class
variables by those of the child
/** Same name data referencing in parent and child classes **/ // parent class
// child class
// test class with main
(save source file to identifiier, pcT.java)
/* String s shows parent
and child, n, variable values of same name, as
// String
s is sent to console
|
OUTPUT
.
C:\NewCode>java pcT Parent's n is Mom.
|
Superclass/Subclass compatibility
A subclass object can be used anywhere a more general superclass object
can be used, so in
OO programming, a variable of a class may actually be referring to
a more specialized subclass
Example Specialized_subclass
s = new Specialized_subclass( );
General_superclass p = s; //
the subclass is being assigned to the type of the superclass
We saw in an earlier example casting between primitive
types. For the following code shows
an example of this, and in passing, what happens
when a cast is made that cannot be correctly
stored in the variable declared. In this case
a meaningless number is stored.
class caster{
public static void main(String[]args){
long l=40000000000L;
// interesting if the explicit
designation L is not included the value is assumee to be an int
// despite it about to be assigned
to a long variable. The compiler reports the value is too
// too big to be stored as an
int. The L resolves this.
System.out.println("l as a long
"+ l );
int i=(int)l;
System.out.println("l's value,
too big for an int, becomes " + i );
// This results in a meaningless
number unless the assigned
// number is actually in the
range of the type declared.
}
}
Casting Reference Types
The rules governing casting reference types may be summarized as follows.
1) a more general object can always hold a more specialized one (parent
= child)
2) reverse the process by casting (child = (child) parent ) //
compiles ok but may be ok at runtime?
3) At runtime the cast must be legal or a ClassCastException
occurs*
4) You cannot cross cast between unrelated classes
5) Every class inherits from, therefore can be cast to Object (i.e.
Vector
stores Object)
* Exception: a recoverable interuption
to normal flow of control
// reminder: instanceof checks
if a reference (on the left-hand side), is an instance, (class or sub-class),
of a given type (on the right-hand
side).
Casting Example
public class FlyingMachine{ . . . }
public class Jet extends FlyingMachine{. . .}
public class Balloon extends FlyingMachine {. . .}
FlyingMachine fm;
// a reference to the parent
Jet F16=new Jet( );
// a child of one sub-type
Balloon zepellin = new Balloon( );
// a child of another sub-type
/*1*/ fm = F16;
// OK, a child can always be assigned to parent type
/*2*/ F16 = zeppellin;
// Won't compile, you can't cross assign unrelated classes
/*3*/ F16 = fm;
// Won't compile, you can't assign
down the inheritance tree
F16 = (Jet)fm;
// BUT with a cast a parent can be assigned to child however
// this may fail at runtime as the check will be made to see if
// assignment is to the same type or that of parent
Quick Inheritance Assignment Summary
P (parent)
// 1) Assigning up is OK , child to parent
P = A;
____|____
//
2) Across is not
A =/=B;
|
|
// 3) Can't assign down, A=/=P, but can cast
down, A=(A)P;
A (child) B (child)
// though at
runtime it be checked to see if it's legal
// At runtime the
expression must resolve to an assignment to the same type or to the parent
type
// or a runtime
error occurs
Polymorphism
Polymorphism means many
forms or shapes and is used
in object oriented programming
to refers to how different behaviours are associated with a same method
name. In java, this
is achieved by the techniques of overloading
and overrriding.
Overloading is considered shallow
polymorphism and is resolved by the compiler. Methods
and constructors can be overloaded. Overriding is deep
polymorhism and is resolved at
dynamically at runtime.
Method Overloading
When methods with the same names are distinguished by variations in
their argument lists they
are said to be overloaded.. The
compiler distinguishes same-name methods by variations in the
1) type 2)
order
& 3) number
of
parameters in the method's signature.
Return
type and
exceptions thrown,
are not of consequence in overloading.
Examples // all are different methods which are overloaded in that they have the same name
public void measure(int i){ }
public void measure(int i, int j){ }
// distinguish by # of parameters
public void measure(int i, short j){ }
// " "
type " "
public void measure(short j, int i){ } //
" "
order " "
/* adding
public String
measure(short z, int x) throws Exception{ //stuff }
would not
be distinguishable from the previous method example.
The identifier
isn't relevent, only the type
*/
Another good example of overloading is provided in the PrintWriter
class with several it's
several print(
) methods, one for each primitive type as well as Object class
and String.
// i.e. void print(boolean b), void print(char c), void print(double d) void print(float f), etc.
Method Overriding
Overriding describes the case where a subclass method has
an identical signature to that
of a method in the parent class, ( the same
method name and number,
type
and order of
parameters) The subclass method effectively overrides
the
superclass' version of the method.
The rules governing overriding are as follows.
1) return types
in
overridden methods must match
2) Overridden
methods cannot
throw new exceptions or exceptions that are more
general than those of the parent method.
3) access
modification cannot be more private than in parent method only
more public.
An example of subclasses overriding
the parent method
class Pop{ // a class with a method as member String getCoffee( ){ String black = "Black thanks"; return black; } } class Tot extends Pop{ // overrides getCoffee String getCoffee( ){ String noThanks = "No thanks"; return noThanks; } } class Dot extends Pop{ // also overrides getCoffee String getCoffee( ){ String sugar = "Sugar please"; return sugar; } } class Host { public static void main(String[] args){ // We will
declare them all to the general parent type to
Pop pop,tot,dot;
// Here's
polymorphism. The parent and subclasses have
System.out.println("How do you like
your coffee?");
|
At runtime, the correct method is chosen based on what object is actually
being referenced.
This allows a class to implement an operation or behaviour which is
unique to itself. ( Methods
with the same name in both a superclass and a subclass are called according
to the runtime
determination of what class is actually being referenced, this accomplished
by class
Class
using
RTTI, Run
Time Type Information )
More on class Class
Every class file has an object of type Class stored in it, a tag which the compiler first calls to get the 'blueprints' for the class it must build from the array of bytes stored in the class file. Class stores vital type information for checking casts at runtime, when classes are dynamically loaded as needed. Class objects may also be used to provide information about each or the different members of a given instance. The information class Class provides is vital to allow the operation of distributed, object-oriented applications to work over networks, assisting java's class loaders to load class objects remotely, as they are called from the java runtime environment ( JRE ). . |
// Notes: Fields and methods
can have same names but it isn't a recommended practice. Speaking
of style,
// 'The Java Language Specification'
states method names should be based on verbs and fields on nouns.
// A group of ovrerloaded
methods would normally be designed to be of related purpose
The final keyword applied to classes
When a class is marked final it becomes
the last in an inheritance line and cannot be subclassed.
The Math class is an example of
a final class. All of Math's methods are static. Math
is made
final to improve performance and to ensure consistent results.
The final keyword signals the
compiler to preload the class rather than leaving it to runtime to
decide which overridden method
to use. final is also used for security reasons.
String class is also a final class.
Making String final prevents the changing
of read-only attributes
in subclasses, as might be possible the String
class'
version of toString( ) could be overridden.
( toString( ) is one of the methods defined in class Object
which
all classes inherit )
The abstract keyword applied to classes
In a sense final and abstract are opposites. final
prevents extending and overriding while
abstract forces overriding to take place. An abstract class
cannot be instantiated. To be
used it must be extended. abstract at the beginning of a class
means zero or more of it's
methods are abstract. A good example of a common abstract class is
the
Component
class.
It is root to all the visual component classes.
Reminder While we
are here, an abstract method has no body. It is incomplete and requires
an implementation to be used. And the rule is, If
a method is marked abstract, the class containing
it must also be marked abstract. |