Inheritance & Polymorphism
Peter Komisar  © Conestoga College      latest version 5.4 / 2006


Inheritance



In this note we talk about inheritance. '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 already existent class definitions. Because a subclass
extends the definition of a parent class, inheritance is also called
extension.

// inheritance is also referred to as extension

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 not necessary as the compiler supplies the
Object class extension for us implicitly. Object is the ultimate parent of
all classes. In a human sense, inheritance implies a sort of 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

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 even across inheritance boundaries. This means a parent
can supply certain utilities to a child class without offering the child
explicit access to these aspects of the parent 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 by removing comments from line containing 'carKeys'
// variable compile and read the compiler report

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

    }     
      }      


The output shows that when the TeenAger class instantiates
it's parent constructor is invoked first. Also note that this example
demonstrates that non-private variables are automatically inherited
and available for use in the child.


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

Another aspect that derives from inheritance is 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.
 

How to inherit

For all the fanfare, the actual inheritance technique is simple. We
already
have had previews of what is involved. If a class Soldier
was 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 thousands of lines of code from it's parent. Notice also by
simply extending a parent how it's class members become 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);
        }
}
// 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);
  }
}


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 thousands
of hours of exhaustive use by thousands of programmers. Bugs
will have been ironed out and fixed. The widget you will use is
most probably bug-free. When you debug code based on these
components, you will look in the new code for problems not the
old. 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.

// The inheritance mechanism allows 'ironed out' code  to be hidden
// while still permitting extension and experimentation to continue.

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.

// inheritance as an organizational technique simplifies maintenance
// of backward compatibility

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.)

// The Inheritance model requires that we are aware of functions and
// variables that are available to a class through inheritance. Practically,
// if we were checking the documentation for a class for a method to
// do something, we should also check the parent specification to see
// what methods it supplies


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



There are a number of analysis tricks and techniques used to decide
what should be a class and what should be a class member. One of
the simplest and most effective techniques for determining if one
class should be a member of a class of a subclass of a class is to
use the "Is a, Has a" rule.

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.

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 yields, " 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 most cases 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 doesn't multiple inherit   
// 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 been designed
to support 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.

In place of multiple inheritance, Java provides the interface. A
class can only be defined as extending a single class but it can
implement as many interfaces as it wants. The following class
skeleton extends one class, Frame and implements two interfaces,
ActionListener and Runnable. Notice two stub methods are
provided. They are the methods the two interfaces define. When
a class implements an interface it takes on the responsibility of
implementing the interface methods.

Example

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

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


Variable Masking



Speaking on the issue of inherited members, there is a unique
situation that arises
with inheritance. 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, a parent class may be 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. We can clarify this
situation using an example.
 

Example

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

Now we can instantiate these classes in another class with a
main( ) method. 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 and
the child value. What about child' 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 that can be used to unmask the parent
variable value from inside the child class.  First, we can instantiate
the child class to the type of the parent. 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.
 

Example         

Parent child =new Child( );   // typing to the Parent
                       

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

Example       

String supersEyes=super.eyes;   // using super  


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

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

// casting the reference to Parent type

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.

Recall that it is always acceptable to make a widening assignment.
We can always assign an 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 to hold. Java can force the truncated value
to be stored in an int even though the number that is stored is relatively
meaningless.

Finally there are some cross assignments which are not legal.

Example   

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

// will not compile whether assigned or cast


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 meaningless truncated value is " + truncatedValue + "." );   
    }
}


Assigning and Casting Reference Types

We cover the ideas involved in assigning and casting reference
types from four different angles. First in a descriptive narrative,
then in a rules summary, followed by a code example and finally
a diagram summary.  Although redundant, the information is all
complimentary and is useful to repeat in different contexts.

Assignment and casting of primitive types  and the assignment
and casting of references have some analogies. The 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
when 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!


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.

Again, comparing to 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 minor 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

Although a cast can be used to force a compile, the second hurdle
that needs to be crossed is whether the code will 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 the runtime finds the cast was
not meaningful and as such illegal, a ClassCastException will be
thrown.

There is really different behaviour in this case between the primitive
and reference type. While the primitive will tolerate a meaningless
cast, the reference cast that is equivalent to meaningless, or more
specifically is illegal, is not tolerated and causes an exception to
be thrown.

The final part of the analogy refers to situations with primitives 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 hierarchal 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.


What we are covering here is not really the whole story. Arrays
and interfaces represent other sets of objects that are governed
by rules of assignment and casting. Generally the rules that apply
to arrays and interfaces are very limited.

In my opinion they make the story overly complicated for the first
pass. We leave them out of our discussion. After you get onto the
general ideas of assignment and casting with class types you can
investigate how the same ideas apply to array and interface types
on your own. )

Following is a collection of classes whose objects are assigned
in various ways
to test the rules summarized above. ( Undo the
comments if you wish to 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 */
    }
}


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   



Polymorphism comes from Greek and means 'many shapes'.
Although in programming shapes may
be construed as having
an association with properties, the common interpretation of
polymorphism is associated with behavioural changes that can
be expressed using methods. Polymorphism involves using
the same name for a number of methods.


Shallow Polymorphism  
// overloading

There is 'shallow polymorphism' that is synonymous with method
overloading. Method overloading is using the same name for a
number of methods, 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.

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.

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

/* adding
    public String measure(short j, int i) throws Exception{ //stuff }
    would not be distinguishable  from the previous method example
*/

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'.

The principles of Inheritance and Polymorphism along with
Abstraction and Encapsulation are the four principle pillars of
object-oriented systems. They work in object-oriented languages
together to create systems of complex and interconnected object
that have been successfully applied to supply a great number
of successful solutions to real-world programming problems. 



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  



Part I  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 


Overloading Exercise


 
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 Exercise 

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?