Introduction: how you have used reference variables thus far...

  • So far, we have always use a reference variable to point to an object of the same class:

  • Now we will use a reference variable to point to an object of a different class:

  • When is it safe/allowed ???
  • What is the effect ???

The information conveyed in a class definition

  • Consider a class definition:

    public class SomeClass
    {
        public int x = 44;
        
        public void method1() 
        {
            System.out.println("SomeClass.m1()");
        }
        
        public void method2() 
        {
            System.out.println("SomeClass.m2()");
        }
    } 

  • We can (1) define variables and (2) create objects with the SomeClass class:

      (1) SomeClass a;   // Defines a reference variable
    
      (2) a = new SomeClass(); // Create a SomeClass object

The information conveyed in a class definition

  • The class definition has another use:

    public class SomeClass
    {
        public int x = 44;
        
        public void method1()
        {
            System.out.println("SomeClass.m1()");
        }
        
        public void method2()
        {
            System.out.println("SomeClass.m2()");
        }
    } 

  • It also specifies the legal (=allowed) member accesses using a SomeClass variable

      a.x            is legal because x is a member variable
      a.method1()    is legal because method1 is a member method
      a.method2()    is legal because method2 is a member method

The correctness of program execution

Suppose a SomeClass variable a is referencing to some arbitrary object:

We can make these legal member access requests:   (1) a.x   (2) a.method1()   (3) a.method2()

The correctness of program execution

Rule: a reference variable must reference to an object that contains all members in a legal request

Reason: the referenced object must perform all actions in the class or else we can have an request error !

The normal way to use objects

The simplest way to satisfy the rule is to reference to an object of the same class:

However: there is another safe (= correct) way due to the inheritance relationship !!

Review:   a subclass inherits all normal members from its superclass

A subclass inherits all the normal members (excluding constructors) from its superclass:

Review:   a subclass object contains a superclass object

A subclass object contains all normal members found in a superclass object:

Review:   a subclass object contains a superclass object

A subclass object contains all normal members even when we override some methods:

Review + intro to polymorphism:   using an instance variable to access members in an object

An instance variable a of the type SomeClass can be used to access the (public) members in SomeClass:

Review + intro to polymorphism:   using an instance variable to access members in an object

An instance variable a of the type NewClass can be used to access the (public) members in NewClass :

A subclass object can perform all actions of a superclass object

Notice that:   a subclass object can perform all actions that a superclass object performs:

 

A subclass object can perform all actions of a superclass object

Therefore, it is safe to use a superclass reference variable to request members in a subclass object:

Java does allow you to access members in a subclass object using a superclass reference variable !

Example that show the legal assignment of a subclass object to a superclass variable

 

public class myProg
{
    public static void main(String[] args)
    {
        SomeClass a; // Defines a reference variable of
	             // type SomeClass
		     // Allowable actions:
		     //     a.x
		     //     a.method1();
		     //     a.method2();

	a = new NewClass(); // Make a reference to a NewClass object

	             // Legal, because the NewClass object
		     // can perform all actions
		     // required by the SomeClass type
    }
} 
  

DEMO: demo/04-inheritance/18-casting/Demo4.java

Dynamic dispatch (a.ka.: late binding)

Furthermore:   the request a.method() will execute the method in the object that a is currently pointing to:

This feature is called "dynamic dispatch" or late binding (decision on which method to run is at the last moment)

Example using a superclass instance variable to access members in NewClass

public class myProg
{
    public static void main(String[] args)
    {
        // New way to access member in NewClass

        SomeClass a = new NewClass(); // Allowed !

        System.out.println(a.x);
        a.method1(); // exec NewClass' method1()
        a.method2();
     // a.method3(); // This is illegal !
    }
} 
public class NewClass extends SomeClass
{
    public void method1() // Override
    {
        System.out.println("**NewClass.m1()");
    }
    
    public void method3()
    {
        System.out.println("**NewClass.m3()");
    }
 
}


  
public class SomeClass
{
    public int x = 44;
    
    public void method1()
    {
        System.out.println("SomeClass.m1()");
    }
    
    public void method2()
    {
        System.out.println("SomeClass.m2()");
    }
 
}
  

DEMO: demo/04-inheritance/18-casting/Demo.java

Because a is pointing to a NewClass object, a.method1() will execute NewClass' method1() eventhough a is a SomeClass variable

Polymorphism

  • Consider the following program:

         SomeClass a; // Superclass reference variable
    
         // Use superclass variable to accces
         // overridden method in superclass
         a = new SomeClass();  // References superclass object
         a.method1();          // Calls SomeClass.method1()
    
         // Use superclass variable to accces
         // overridden method in subclass
         a = new NewClass();   // References subclass object
         a.method1();          // Calls NewClass.method1() 

    The same expression a.method1() invokes different methods !!!

  • Polymorphism = the phenomenon that the same expression (= program code) can result in different actions

  • Polymorphism is caused by using a superclass reference variable to access overridden members in the superclass and their subclasses and late binding

DEMO: demo/04-inheritance/18-casting/Demo2.java

The reverse case --- a superclass object may perform fewer actions than a subclass object

Notice:   a subclass object may perform fewer actions that a subclass object can perform:

 

A subclass object can perform more actions than a superclass object

Therefore, it is illegal to use a subclass reference variable to access members in a superclass object:

E.g.:   the action a.method3() is illegal because there is no method3() defined inside a SomeClass object

Example that show the illegal assignment of a superclass object to a subclass variable

 

public class myProg
{
    public static void main(String[] args)
    {
        NewClass a; // Defines a reference variable of
	            // type NewClass
		    // Allowable actions:
		    //     a.x
		    //     a.method1();
		    //     a.method2();
		    //     a.method3();

	a = new SomeClass(); // Make a reference to a SomeClass object

	            // Illegal, because the SomeClass object
		    // cannot perform:
		    //       a.method3();
    }
} 
  

DEMO: demo/04-inheritance/18-casting/Demo3.java