/*
   This file tests how polymorphism works with overloaded methods.

   When you run this program, notice how the class of an object (not
   the type of the reference variable) determines which class an
   overridden method comes from, but the type of a reference variable
   (not the class of the object) determines which overloaded method is
   used.

   This file defines two class hierarchies, the hierarchy ClassA, ClassB,
   ClassC, and the hierarchy Class1, Class2, Class3.

   In Class1 and Class2 the method methodABC is both overridden and
   overloaded. The class hierarchy ClassA, ClassB, is used to
   occomplish the overloading. The class ClassC is used to show that
   the Java compiler chooses the "closest match" for overloaded methods.
*/

class ClassA { public String toString() {return "ClassA";} }

class ClassB extends ClassA { public String toString() {return "ClassB";} }

class ClassC extends ClassB { public String toString() {return "ClassC";} }


class Class1
{
   public String methodAB(ClassA x)
   {return "methodAB in Class1 with parameter of type ClassA pointing to object from " + x;}

   public String methodAB(ClassB x)
   {return "methodAB in Class1 with parameter of type ClassB pointing to object from " + x;}

}//Class1


class Class2 extends Class1
{
   public String methodAB(ClassA x)
   {return "methodAB in Class2 with parameter of type ClassA pointing to object from " + x;}

   public String methodAB(ClassB x)
   {return "methodAB in Class2 with parameter of type ClassB pointing to object from " + x;}

}//Class2


public class PolymorphismAndOverloading
{
   public static void main(String[] args)
   {
     ClassA a;
     ClassB b;
     ClassC c;

     Class1 z = new Class2();

     a = new ClassA();
     System.out.println(  z.methodAB(a) );

     a = new ClassB();
     System.out.println(  z.methodAB(a) );

     a = new ClassC();
     System.out.println(  z.methodAB(a) );

     b = new ClassB();
     System.out.println(  z.methodAB(b) );

     b = new ClassC();
     System.out.println(  z.methodAB(b) );

     c = new ClassC();
     System.out.println(  z.methodAB(c) );

   }//main

}//PolymorphismAndOverloading