import java.io.Serializable;

class TestAssignment{

    public static void main(String[] args){
    
    /** Class and Interface assignments **********************************/
                   
        A a1       = new B();    // B is a subclass of A
  //    B b1       = new A();    // compile-error: incompatible types
        
        InA inA    = new C();    // C implements InA
        InB inB    = new D();    // D implements InB
        InA inA2   = new D();    // D implements InA as a superinterface
  //    InB inB2   = new C();    // compile-error: incompatible types
        
        inA        = inB;        // InA is a superinterface of InB
  //    inB        = inA;        // compile-error: incompatible types        
        
        Object o1  = inA;        // an Object type can take any reference
        Object o2  = inB;
        Object o3  = new C();
  //    C      c   = new Object(); // compile-error: incompatible types
        
        B    b2    = null;       // any object reference can take a null
        InA  inA3  = null;
        
       System.out.println("Class of object a1    \t -> " + a1.toString());
       System.out.println("Class of object o1    \t -> " + o1.toString());       
       System.out.println("Class of object o2    \t -> " + o2.toString()); 
       System.out.println("Class of object o3    \t -> " + o3.toString());              
       
       // following throws a runtime java.lang.NullPointerException
//     System.out.println("Class of object b2    \t -> " + b2.toString());

      /** Array assignments **********************************************/

      int intArr[]  = { 1,2,3 };
      int intArr1[] = intArr;       // compiles ok
      
//    String arr[] = new A();       // compile-error: incompatible types
//    String arr[] = inA;           // compile-error: incompatible types

      Object        obj = intArr;   // compiles ok
//                  inA = intArr;   // compile-error: incompatible types
      Serializable  inS = intArr;   // compiles ok
      Cloneable     inC = intArr;   // compiles ok

    }


}

class A {
  public String toString(){
    return("Class A");
  }
}

class B extends A {
  public String toString(){
    return ("Class B");
  }
}

class C implements InA {
  public String toString(){
    return ("Class C");
  }
}

class D implements InB {
  public String toString(){
    return ("Class D");
  }

}

interface InA {
}

interface InB extends InA {
}
