
// This program exercises your understanding of references in Java.

// Parts of it are intentionally hard to understand.  But it is well
// worth trying to figure it out since it gives your understanding of
// references in Java a very good work-out.

import java.io.*;

class Tricky {
  // Create an object to read lines from the keyboard.
  public static BufferedReader keyBoard = new BufferedReader( new InputStreamReader(System.in)); 
  
  public static void main(String[] args) {

    // The code in the published lecture notes:
    A a = new A();  
    B b = new B();
    A.sm(); 
    I i = b;   
    P p = (P) i;
    System.out.println("i equals b: " + i.equals(b));
    b.sm();
    i.m();   
    p.m();
    b.m().sm();

    System.out.println();
    pause();
    
    // Plus MORE! Oh no.... 
    // Silly print statements, but notice 
    // the references to ANSWER in interface I
    System.out.println(
       "The answer to the meaning of life and everything is " +
        A.ANSWER);
    System.out.println("Yes, that's right, " + a.ANSWER);
    System.out.println("But what is the question?");
    System.out.println("See Hitch Hiker's Guide to the Galaxy (for fun).\n");

    // i.sm();  // What happens if you uncomment this line? 

    // A necessary widening cast...
    // ... but in a static reference with poor style:
    ((P) b).sm(); // P's (static) sm() method
    b.sm();       // Previous line without the cast gives different results.
    
    System.out.println();
    
    // Note that the above code does not follow the stylistic rule
    // for the clear reference to static members, namely:
    //   Static Reference Style: 
    //     Always use only a class name in a reference to an
    //     uninherited static member.
    // The lines above which break this rule are rewritten in an equivalent
    // but clearer form below:
    //   b.sm();       // should be written: B.sm();
    //   b.m().sm();   // should be written: b.m(); P.sm();
    //   ((P) b).sm(); // should be written: P.sm();
    //   a.ANSWER and A.ANSWER should be referenced as I.ANSWER
    // Note that these are MUCH easier to understand because the classname
    // in the reference tells the reader that the method must be static.
     
    pause();

    // Finally, if your brain isn't bent yet, how about that newMethod?
    System.out.println("main's call to a.newMethod():");
    a.newMethod();

    pause();

    System.out.println("main's call to b.newMethod():");
    b.newMethod();

    System.out.println("main is done");

    // Hint: Check out previous midterm and final exams.  This sort
    // of mind bending exercise on finding targets is a common question.
  }

  /**  
   * A simple method to pause the program until a key is struck.
   */
  static void pause() {
    System.out.println("Press Enter to continue...");
    try {
      keyBoard.readLine();
    } catch (EOFException e) {
      System.out.println("EoF encountered on input.  Bye bye.");
    } catch (IOException e) {
      System.out.println("Error encountered on input. Yikes! Bye bye.");
    }
    System.out.println();
  }
}
