Inheritance & Polymorphism
Peter Komisar   ©   Conestoga College  latest version  5.8  Sept /  2010


Inheritance



In this note we talk about inheritance. We have seen that
'encapsulation' describes the idea of enclosing a set of
related elements into a class structure. This structure is
then used to create objects of that class. Inheritance takes
the idea a step further by allowing new classes to be built
as extensions of pre-existing class definitions. Because
a subclass extends the definition of a parent class,
inheritance is also called extension.

// inheritance is also referred to as extension

Let us preview the extension mechanism with an example.
It's the 'extends' keyword that is used to create a class that
inherits the attributes of a parent class.


Example

class Parent extends Child



The Root Object

In Java, only the root class, 'Object' has no parent. We have
created many classes in our examples and we don't usually
include an explicit 'extends' clause. This is because the
compiler supplies the Object class extension implicitly.

In a human sense, inheritance might imply an extension
through time. The only 'time' aspect there is to Java
inheritance is a parent class has to exist before a child
class can be built on it.

// all classes are implicit descendants of 'Object class

Java's Inheritance Mechanism

For all the fanfare, the actual inheritance technique is
simple as
was shown above. If a class Soldier is to be
subclassed to
create a class called DemolitionExpert
an 'extends' class is included after the class name

indicating that this new class is a subclass of the stated
parent class.

Example       

class DemolitionExpert extends Soldier { // add specializations  }


Let's create a more elaborate example. 
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 BilingualButton class
defined below extends the parent class to create an
entirely new class.

This extension was accomplished with just a few lines
of code yet inherits hundreds of lines of code from it's
parent.

Inheritance Makes Parent (non-private) Members Available

Notice also by simply extending a parent how the parent's
class members become readily available. This is evident in
the following code example where the setText( ) method is
called without having had to define it in the class.


Example

import javax.swing.*;

class BilingualButton  extends JButton{
        BilingualButton(String english, String french){
        setText(english + " / " + french);
        }
}  // calls setText() which it inherits from JButton
// a class with a main method to run and show the new button
class bT{
public static void main(String[] args){
  JFrame jf=new JFrame();
  jf.getContentPane().add(new BilingualButton("dog","chien"));
  jf.setSize(400,300);
  jf.setVisible(true);
  }
}

A Subclass Can Access Non-private Inherited Members

Let us assume child and parent are in the same package.

A subclass inherits all the non-private members of the parent
as if they were defined in the subclass explicitly. This is not the
case for members that are marked 'private'. The 'private' modifier
effect extends across inheritance boundaries. This means a
parent can supply certain utilities to a child class without allowing
the child to access to specific items in the parent's code.

To describe the benefit of this arrangement in human terms,
a parent's car keys and credit cards may be considered as
being private. A child may benefit from the transportation
and goods the parents resources may supply without being
permitted to access and control these resources.


Example

private String creditCard, carKeys;     

// will not be accessible to a child class however a public
// method in the parent that accesses this value may make
// these resource values available to the child class

Example

class Parent{
private String carKeys ="miata";
public String houseKeys="townhouse";
      Parent( ){
        System.out.println
        ("Being the parent I can access my " + carKeys);
        }
     }
       
class TeenAger extends Parent{
      TeenAger( ){
        System.out.println
       ("Being the teen I have access to " + houseKeys);
 /* System.out.println("I have access to " + carKeys); */
      
// This class won't compile while referencing 
the private
// variable of the parent
. Test this by removing comments
// from line containing 'carKeys'  and it's associated out
// statement. Compile and read the compiler report

          }
        }      
       
class InheritanceDemo{
     public static void main(String[]args){
        new Parent( ); // will show parent accessing keys
       new TeenAger( );

       }     
   }      

Output

[peter@localhost Examples]$ java InheritanceDemo
Being the parent I can access my miata
Being the parent I can access my miata
Being the teen I have access to townhouse

Superclass Constructors are Expressed First

Notice the redundancy in the output. When the TeenAger
class is instantiated, it first invokes the parent constructor
resulting in a repeat of the parent's System.out. statement.
The output also demonstrates that the child has no problem
referencing the parent's public variables, even though
the child class did not declare them.

// an extension first calls the constructor of it's parent

Inheritance leads to the creation of class hierarchies that
increase in specialization as the inheritance tree grows.
This is the only logical direction it can go, since all children
inherit the type of the parent and then go on to add details
and variations. The child class increases in complexity
relative to the parent.

// Inheritance leads to class hierarchies of increasingly
// specialized classes


Other Benefits of Inheritance

Beyond providing an easy way for programmers to inherit
'instant' code foundations for their own designs, inheritance
also allows bug-free stability to be incorporated into a Java
program. The JButton being extended in the example benefits
from the fixes provided by legions of programmers. 

It is counter-productive to allow ironed-out to be modified.
Inheritance provides a way to incrementally build on a stable
legacy of code and hide well-tested work from exposure to
experimentation and the introduction of new errors.

Inheritance also provides a good mechanism to ensure that
compatibility with future language versions is maintained
and that newer versions of classes do not break compatibility
with old specifications.


Library Checks For Members Should Include Parent Members

As stated earlier, this design results in parent, non-private
class members being accessible to child classes. (Technically,
the exception is a class member with default access is not
available to child classes defined outside the package that
the parent is defined in.)

If a parent has a non-private variable or 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. This was exampled above where
the JButton's setText( ) method was called even though it wasn't
defined in the child class.

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. 

This brings up the practical issue of checking parent classes
to find what inherited members are available to the class. If
in the API a method isn't in the parent class, the next place
to look is in the parent's parent and so on all the way back
to Object class.)

// Parent members back to Object are part of what's available to a child class


The " Is a " vs. " Has a " Test          



There are a number of analysis tricks and techniques that may
be used to decide what should be a class and what should be
a class member.

One simple technique is the "Is a, Has a" rule. It is effective for
determining if one class should be a member of a class of a
subclass of a class or an extension of that class.

Assume you have a Car class and an ID class and you want to
determine what relationship they should have with each other.
You can create the statement, " A car has an ID" and another
statement, "A car is an ID ". The first one makes sense. This
tips you off that a Car class will have an object of the ID class
as a member.

// this assumes you use a class rather than just a
// variable to describe an ID.


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 1

  class Car{
    Car( ){
       ID id=new ID ( );
       // etc.
       }
    }

A second example, consider a mammal class and a dog class.
Applying the test yield the conditions, " A dog 'has a' mammal "
and a " A dog 'is a' mammal ". Though  "A dog 'has a' mammal",
may be true with respect to it's dinner, in the way we are looking
at this it this doesn't make sense. "A dog 'is a' mammal" is the
sense we are looking for. This signals us that A dog should be a
subclass of the mammal class.

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.


Example 2

class Dog extends Mammal {
                         // etc.
                       }


Java Classes Do Not Use Multiple Inheritance
// a class can only extend a single parent class

Notice we have never shown a situation where a class inherits
from more than one parent class. Java might have supported
multiple inheritance as C++ and other languages do. The price
that has be paid to support of multiple inheritance is added
complication.

Extra rules and referencing techniques have to be supplied
to distinguish inherited members that have the same name
in both parents. Java simplifies this situation by using a single
inheritance model. Each class can only inherit from one parent.


Interfaces Replace Multiple Inheritance in Java

In place of multiple inheritance, Java provides the interface. A
class can only be defined as extending a single parent but it can
implement as many interfaces as needed. In the next example,
the class extends one class, Frame. It also implements the
interfaces Runnable. The run( ) method is defined in the
Runnable interface. It is the duty of the class that implements an
interface to supply implementations for any methods that an
interface it is implementing defines.

Example

import java.awt.*;
import java.awt.event.*;

class Multi extends Frame implements ActionListener, Runnable{
   public void run( ){ }
   public void actionPerformed(ActionEvent ae){
   }
}

// later we see an example showing Java Interfaces may multiply inherit


Variable Masking



Inheritance introduces
a unique situation with respect
to class members. Class members can be defined
identically in both the parent and
child. With variables
this means the same type and identifier is used. With
methods identical
signatures are used.

Dealing with variables first, consider a parent class is
defined and a variable declared and given a value. A
child of this parent class may now be
created with a
variable that is declared identically to the
one used in
the parent. The question becomes if the child variable
is referenced
which value will it take, the child's value
or that of the parent. The following code creates this
scenario.

 

Example

    class Parent{
      String eyeColor ="brown";
       }
     // child class
    class Child extends Parent{
       String eyeColor = "blue";
       }                                                                                                                               

We can instantiate these classes inside the main( ) method
of another class. First the two classes are instantiated and
then each member is referenced using the dot operator.


Example
                                       
                                                                                                                    
class Traits{
 public static void main(String args[] ){
    Parent parent=new Parent( );
    Child child=new Child( );
    System.out.println
      ( "The parent's eye color is " + parent.eyeColor + "." );

    System.out.println
       ( "The child's eye color is " + child.eyeColor + "." );

   }
}

Everything behaves as expected. The parents value is
exposed as is the child value. What about the child's
inherited value for eyes. Where did it go? It didn't go
anywhere. It's value is said to be 'masked' or 'hidden'
by the child variable. You may now ask how the parent
variable might be exposed or unmasked.
 

Unmasking Hidden Variables

There are a few techniques Java supplies to unmask a
parent variable value from inside the child class.  First,
we can instantiate the child class to the type of the parent.  


Example 
     // typing to the Parent     

Parent child =new Child( );

This will expose the parent value for the variable. This
shows that the value of variables is associated with the
static type template that defines the parent class.                       

Another way to effect the same thing is to use the keyword
'super' to reference the parent data structure. 

Example      // using super  

String supersEyes=super.eyes; 


Finally the child type can be cast to the parent type to
expose the parent value. The extra brackets are being
used to make explicitly clear that the cast is done
before
the variable is accessed.
 

Example // casting the reference to Parent type

String castEyes=((Parent)c).n;

We can collect these techniques and add them to the
Child class we defined
earlier to show their use. All will
expose the parent value for eyeColor.


Code Sample 

    class Parent{
       String eyeColor ="hazel";
       }
       // child class
      class Child extends Parent{
       String storeSuper=super.eyeColor;
       }

class Traits{
   public static void main(String args[] ){
     Parent parent=new Parent( );
     Child child=new Child( );
     Parent childToParent=new Child( );
     System.out.println( "\n" + "Accessing Masked Parent Variable Values:" + "\n");
     System.out.println
     ("- via parent typing of child:       "     + childToParent.eyeColor);
     System.out.println
     ("- via a super reference to parent:  " +  child.storeSuper);
     System.out.println
     ("- via casting child to parent type: "   +  ((Parent)child).eyeColor);
   }
}


Assignment and Casting Reference Types



Example of a Cast With Primitive Types

The following section explains the key ideas in assigning
and casting reference types. Before proceeding with the
issue of reference type casting, we can refresh our memory
in how casting is used with primitive types.


Widening Assignments Are Always Acceptable

Recall that it is always acceptable to make a widening
assignment. We can always assign a byte value to an
int and be sure our value is stored correctly.

Example  

byte small = 28;
int big =  small;  // always legal

Also remember that casting can be used with primitive types
to force a narrowing conversion. In the following example we
create a number that is way too big for an int type to hold.
Java can force the truncated value to be stored in an int even
though the number that is stored is relatively meaningless.

Narrowing Assignments Can be Done By Casting
// but meaningless values may result

Example

class Force{
public static void main(String[]args){
    long bigNumber = 10000000000L;     // ten  billion
    int truncatedValue = (int)bigNumber;
    System.out.println
    ("\n" + "Only the lower digits of " + bigNumber + " are stored in the int cast.\n"
          + "The somewhat meaningless truncated value is " + truncatedValue + "." );   
    }
}

// relatively meaningless value arises from the truncation due to cast
// note, it might be a meaningful value if the truncation was what was sought!


Some Casts Are Illegal

Finally there are some cross assignments which are not
legal. In Java you can't cast a boolean to any other type.

Example   

boolean boo = true;
int number =(int) boo;  

// will not compile whether assigned or cast


Assigning and Casting Reference Types

Now let us consider assigning and casting reference types.
We do this in a number of ways. First we use a description
comparing reference assignment to primitive assignment. 
Then we generate a set of rules. Next the rules are shown
in code examples. Finally we do a diagram summary.  

Assignment and casting of primitive and reference types
have some similarities. These parallel exists due to the
relationship classes share through inheritance. Where with
primitives, widening assignments are always legal, similarly,
with reference types a more specialized subclass can always
be assigned to a more general Parent. We get an inclination
of this should we create a class and type it to Object type as
in the following example.

Example  

Object o;
JLabel label=new JLabel( );
o=label;    // this is ok and will compile and run!

// with both primitives and reference types widening assignments
// are always legal


The reason this is OK is that a subclass can always be
assigned the type of a more general parent. Recall that
JLabel in addition to many other types that it represents
can satisfy the type set of Object, that is, the collection
of methods defined in Object class. This is similar to
a widening assignment with primitives.

Like with primitives, where a narrowing conversion is
not assignable, a cast can be used to force the fit, even
if the result is the storage of a meaningless number. In
reference types, a parent type can't be assigned to a
child type. The compiler will not permit it. However, a
parent can always be cast to a child type to get by the
compiler.

Example    

JLabel label;
Object object=new Object( );
label= (JLabel)object;      

// will compile with the cast but not otherwise

// a cautionary note:  When an object is restricted to the type of a parent
// only the parent type methods and variables will be available. The child
// members
are not part of the parent type definition


What Might Compile Might Still Not Run

Although a cast can be used to force a compile, a second
hurdle exists with reference types, that of execution at runtime.
Code in casted form may or may not run.

In the final analysis the object that has been cast has to
be the same type as the receiving reference or a subclass
of it. This is similar to the situation with primitives where
the cast may or not be meaningful. In the case of reference
types, If at runtime the cast is found to be meaningless and
as such illegal the runtime will throw a ClassCastException.

// illegal casts show at runtime as ClassCastExceptions

In the comparison of primitive and reference type casting
parallels fall apart. While a primitive meaningless cast is
tolerated , the reference cast that is equivalent to meaningless,
or more specifically is illegal, is not tolerated and causes
an exception to be thrown.

// a primitive meaningless cast is tolerated but an illegal reference
// cast is not tolerated, reflected in the throwing of an exception.

The final part of the analogy refers to actions that are plainly
not allowed. For instance boolean type cannot be assigned
or cast to any of the other primitive types. A similar situation
exists with reference types in that in no case can cross
hierarchical assignments or casts be made. For instance a
Vector object can never be assigned or cast to a JLabel
reference or visa versa. 

What we have just described is summarized in the following
rules.
 

Summary of Rules Governing Casting and Assigning Reference Types

1) A child  object can always be assigned to a parent reference.
//  parent = child;
 
2) A parent cast to a child type will compile but may not run.
// child=(child)parent;

3) At runtime the cast must be legal, legal meaning the object being
cast must be the same type or a subtype of the receiving reference.
A ClassCastException will be thrown if this is not the case.

4) You cannot cross cast between unrelated classes

5) Every type inherits from, therefore can be cast to Object

//  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) there instanceof can check to see if a cast is legal.


Assigning and Casting Arrays and Interfaces

What we are covering here is not the whole story. Arrays and
interfaces represent other sets of objects that are governed by
rules of assignment and casting. Generally arrays and interfaces
are very limited in how they can be assigned or cast. For instance,
both arrays and interfaces can been assigned or cast to Object type.

The story becomes overly complicated for a first pass dealing with
arrays and interfaces so they are left out of this discussion. You can
investigate assigning and casting these data types at a later time.


Object Casting Example

Following is a collection of classes whose objects are assigned
in various ways
to test the rules summarized above. ( Undo the
comments to test each scenario.)
 

Assignment and Casting Example

class FlyingMachine{ }
class Jet extends FlyingMachine{ }
class Balloon extends FlyingMachine { }

class Air{
public static void main(String[]args){
    FlyingMachine saucer=new FlyingMachine( );
    Jet F16=new Jet( );   // child one
    Balloon zep = new Balloon( );  // child two 

/* 1. The following compiles and runs as a child is assigned to a parent*/
//    saucer=F16;
/* 2 The next statement doesn't compile. Cross assignment of incompatible types*/
//   F16 = zep;
 /*3 Casting doesn't help. The types are inconvertible*/
//   F16 =(Jet) zep;
 /*4  Doesn't compile. Can't assign parent to child */
//   F16 = saucer;
 /* 5 Compiles but may not run, depending if the cast is legal. */
//    F16 = (Jet)saucer;
 /* Legal means the object assigned must be the type of the receiving reference or a subclass */
    }
}

Finally we summarize in the following diagram.


Quick Inheritance Assignment Summary

                    P (parent)         //  1) assigning up is OK , child to parent   P = A;
            ____|____               //   2) neither cross assigning or casting are allowed  A =/=B;
            |                |              //   3) Can't Assign Down, A=/=P, but can cast down, A=(A)P;
    (child) A           B (child)    //  though at runtime it be checked to see if it's legal
 


//  Legal means at runtime the object  must the same or a
// subtype of the type of the reference receiving the object


Polymorphism   



The term 'polymorphism' comes from the Greek meaning
'many shapes'. Although in programming shapes may
be
construed as having an association with properties, the
common interpretation of polymorphism in an object-oriented
programming language is associated with behavioural changes
that can be expressed using methods. Practically, polymorphism
involves using the same name for a number of methods.


Shallow Polymorphism
  
// overloading

'Shallow polymorphism' is synonymous with method overloading.
Method overloading involves using the same name for a number
of methods within a class, distinguishing between them by variations
in their argument lists. Shallow polymorphism or overloading can
also be applied to constructors. In the case of overloading, methods
with the same name behave differently depending on what
arguments are passed to them.

// shallow polymorphism is method overloading within a class


Deep Polymorphism
        // overriding 

Deep polymorphism is directly related to inheritance. Deep
polymorphism is popularly known as overriding. A method in a
subclass may perfectly mask a method defined in a parent, by
supplying the same method with an identical method signature,
similar to the way variables in a child class masked the values
attributed to the same variables in the parent.

// deep polymorphism or overriding occurs across inheritance relationships,
// similar to variable masking

Polymorphic behaviour comes into play when subclasses provide
different behaviour than the parent for the same method definition.
Consider an abstract motion( ) method defined for a generic aquatic
creature. Now consider how differently they would be exercised in
the implementation that describes the movement of a jellyfish
compared to a starfish.
 

Method Overloading  // shallow polymorphism

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 type, order
and number of parameters in a method signature. Return type and
exceptions thrown are not of consequence in overloading.

Overloaded Signatures are Distinguished by Parameter:

// Return type and exceptions thrown, are not of consequence in overloading.

The following example shows several overloaded forms of a method
called 'measure'.


Examples
 
  // same-name methods with overloaded signatures

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  "      "

Another good example of overloading is the many print( ) methods
in the PrintWriter
where a different one is defined for each primitive.
 

Method Overriding    // deep polymorphism

Overriding describes the case where a subclass method has an
identical signature
to that of a method in the parent class. This
includes the same method identifier and the same number, type
and order of parameters. The subclass method effectively overrides
the superclass' variable. Overriding is stricter than overloading. In
addition to the rules of overloading these additional restrictions
are applied to overridden methods.

Additional Rules Regarding Overriding

1) method signatures including 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 the parent
    method, only more public.


Overriding Code Example

 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
  // show the parent type can act as type for subclasses

  Pop pop,tot,dot;

// caution: typing all the classes to the parent Pop
// type is being done to reveal
mechanical aspects
// of the Java language. In 
practice you would not
// normally type your classes like this unless there
// was a good reason for doing so

  pop = new Pop( );
  tot = new Tot( );
  dot = new Dot( );

  // Here's polymorphism at work. The parent and subclasses
  //  have the
same operations called but all behaves differently

    System.out.println("How do you like your coffee?");
    System.out.println("Pop? " + pop.getCoffee());
    System.out.println("Tot? " + tot.getCoffee());
    System.out.println("Dot? " + dot.getCoffee());
    }
  }

Dynamic Binding

Recall how variables of objects that had been declared to the
parent type, derived their values from the parent definition. If
you run the above code you will see that Java methods are not
influenced by being declared to the type of the parent. (All the
classes above are typed to the parent class, Pop.)

Instead methods are selected based on what type the actual
object being assigned is. So in the above, the overridden
method of each subclass is expressed. Where the variables
are determined statically at compile time, the methods
selected are being determined dynamically at runtime when
the objects are created, inspected for legality and being
assigned. ( This job is performed by a special informational
class called 'Class'.)



Self Test                                             Self Test With Answers



1) Which of the following statements is not correct. In Java inheritance

a) a class can inherit from multiple parent classes
b) private variables are not accessible to a child class
c) extends is the keyword used by a subclass to extend a parent
d) inheritance provides an easy way to build on earlier work.
 

2) Inheritance assists development in the following ways. Pick the
    incorrect statement.

a) improves eases of building on existing work
b) provides protection from entering bugs into tested code
c) permits maintenance of version compatibility
d) Provides access to all inherited code and features.
 

3) Masked parent variables values can be revealed by the following.
    Pick the incorrect statement.

     a) casting a child variable to the parent type
     b) using super to reference the parent object
     c) declaring an object to the parent type
     d) calling toParent( ) passing in the hidden variable
 

4) Consider the following classes.

 class  Water{  /* H20 */ }
class  Mist  extends Water{/* air jet over water */}
class  Steam extends Water{ /* boiling water  */ }

class TestWater
      {
      public static void main(String[]args)
      {
      Water water;
      Mist mist=new Mist( );
      Steam steam = new Steam( );
      water = new Water( );
      steam = (Steam)water;
      }
      }

This code              
             a ) won't compile
             b ) will compile and run
            c ) will compile but won't run
            d ) will compile and may run
 

5) Which of the following is not true? With respect for overriding,

a)  Overriding is related to inheritance
b)  Overridden methods may differ in return type.
c)  Overridden methods share the same signature
d)  Overridden methods may throw different Exceptions
 

6 ) Which of the following factors is only significant to one of overloading and overriding?

a) type
b) order
c) number
d) return type

7)

class X{
   String t="XX";
   String getT( ){
   String o = "XY";
   return o;
   }
 }
class Y extends X{
   String t="YY";
   String getT( ){
   String o="YX";
   return o;
   }
 }

class XY {
  public static void main(String[]args){
   X xy = new Y( );
   System.out.println( xy.t + " " + xy.getT( ) );
   }
}

a ) XX XY
b)  YY YX
c)  XX YX
d)  YY XY
 

8) Select which two of the following methods the compile will not be able to distinguish

a) private void measure(int i){ }
b) void measure(int i, int j){ }
c) protected  void measure(int i, short j){ }
d) public void measure(short j){ }
e) void measure(int k, int x) { }
 


Exercise

// Please put your name, topic of the lecture associated with the assignment
// and a number, at the head of the assignment. ( This is assignment 1. )
// Include the questions and it's number before your answers where appropriate.



Part I  // optional

Here is another example that demonstrates Java' s built
in overriding behaviour.

Example

class GP
     { int x=1;
       void out(){
        System.out.println("Grand Parent Method Version");    
        }
     }
 
class P extends GP
     {
      int x=2;
      void out(){
        System.out.println(" Parent Method Version");    
        }
     }
 
class C extends P
     {
     int x=3;
     void out(){
        System.out.println("Child Method Version");    
        } 
 
     } 

class GPRun
    {
public static void main(String[]args)
      {
      GP gpc=new C();
      System.out.println(gpc.x);
      gpc.out();
      P pc =new C();
      System.out.println(pc.x);
      pc.out();

      C c =new C();
      System.out.println(c.x);
      c.out();
      }    
    // typing doesn't unmask overriding
    }  

OUTPUT

C:\Documents and Settings\Peter\My Documents\J2\Examples>java GPRun
1
Child Method Version
2
Child Method Version
3
Child Method Version


Questions

1 ) Create a generic parent class that define methods for walking and talking.

2) Create three subclasses of the generic parent and override the walking and talking
    methods so they supply specialized behaviour for the new classes.

3) In each of the three classes create another method, eating sleeping, fishing etc.
    Provide overloaded versions of the method that can be used to demonstrate the
    functions use in different settings. (i.e. eating at home, at a restaurant, by the
    campfire etc. )


Part II 
// hand in, make sure you answer all the questions

Overloading

public class Overloading{

public static void main(String[] args){
   int i = 123;
   byte j = 127;
   Overloading ol= new Overloading();

   ol.M( i , j );
   ol.M( j , i );

}
/** Here's the two overloaded versions of M method */

 void M(int i, byte j){
  System.out.println(" int i is first, " + i + " and " + " byte j is next, "+ j);
  }
 void M(byte j, int i){
  System.out.println(" Here byte j is first, " + j + " and " + " int i is second, "+ i);
  }
}

Overloading Question

Q1 Overloaded methods are distinguished by the compiler in three ways. Name
      the three ways and state which the above two lines of code demonstrate.

Overriding 

class P{
   int Variable=7;
   void M(){System.out.println(" P method version ");
   }
}
class C extends P{
   int Variable=11;
   void M( ){System.out.println(" C method version ");
   }
}
class OverRideTest{
   public static void main(String[] args){
     P pcmix=null;
     P p=new P( );
     C c=new C( );
     pcmix=c;               // assigning child to parent type
     p.M( );
     c.M( );
     pcmix.M( );

System.out.println(" Referencing parent object for it's variable, Variable is " + p.Variable);
System.out.println(" Referencing child object for it's variable, Variable is " + c.Variable);
System.out.println(" Referencing pcmix object for it's variable, Variable is " + pcmix.Variable);
  }
}

Overriding Questions

1) a) For parent object, p, which value of variable is called(p or c)?
    b) For child object, c, which value of variable is called (p or c)?
    c) For child assigned to parent type variable, pcmix which value

        of variable is called (p or c)?

2) a) For parent object, p, which version of method is called(p or c)?
    b) For child object, c, which version of method is called(p or c?
    c) For child assigned to parent type variable, pcmix which version
       of method is called (p or c)?

3)  What conclusion can you draw from these results?