import java.util.Scanner;
import csci2341.Utilities;

/**
 * A program to demonstrate inheritance using Parent and Child classes.
 *
 * @author Mark Young (A00000000)
 */
public class TestChildren {

    public static void main(String[] args) {

        // Basic Parent (see slide 39)
        Parent p = new Parent();
        p.setValue("Frank");
        System.out.println("Objects in the parent class have a value.");
        System.out.println("That value is returned using "
                + "the getValue() method.");
        System.out.println("That value is set using "
                + "the setValue() method.");
        System.out.println("I have set this Parent object's value "
                + "to \"Frank\".");
        System.out.println();
        System.out.println("Parent's value is: " + p.getValue());
        Utilities.pause();

        // About inheritance
        System.out.println("Classes that extend Parent "
                + "get the getValue and setValue methods for free.");
        System.out.println("Each of the following children "
                + "sets its value to \"Fred\".");
        Utilities.pause();

        // Basic Child
        Child1 c1 = new Child1();
        c1.setValue("Fred");
        System.out.println("An object of type Child1 "
                + "uses the getValue method it inherited.");
        System.out.println();
        c1.sayValue();
        Utilities.pause();

        // Child with getValue that returns "Ba-ba"
        Child2 c2 = new Child2();
        c2.setValue("Fred");
        System.out.println("An object of type Child2 "
                + "overrides its getValue method "
                + "to return \"Ba-ba\".");
        System.out.println();
        c2.sayValue();
        Utilities.pause();

        // Child with getValue that changes r to w
        Child3 c3 = new Child3();
        c3.setValue("Fred");
        System.out.println("An object of type Child3 "
                + "overrides its getValue method "
                + "to replace any Rs in its value "
                + "with Ws.");
        System.out.println();
        c3.sayValue();
        Utilities.pause();

        // Inheritance and Polymorphism
        System.out.println("The printValue method expects to be given "
                + "an object of type Parent.");
        System.out.println("Each Child class extends the Parent class, "
                + "and so is acceptable as an object of type Parent!");
        System.out.println();
        System.out.println("But even so, each child uses it own getValue method.");
        System.out.println();
        printValue("p", p);
        printValue("c1", c1);
        printValue("c2", c2);
        printValue("c3", c3);
        Utilities.pause();

        // And more
        System.out.println("The doThis method expects a Child1 object.");
        System.out.println("Only a Child1 object will do!");
        System.out.println();
        // doThis(p);   // doesn't work -- expects Child1
        doThis(c1);     // works -- c1 is a Child1
        // doThis(c2);  // doesn't work -- expects Child1
        // doThis(c3);  // doesn't work -- expects Child1
        Utilities.pause();
    }

    /**
     * Print the "variable name" along with the value of that object.
     * Say what type the object is.
     *
     * @param name the "variable name" -- as provided by the caller
     * @param obj the object to call the getValue method on
     */
    public static void printValue(String name, Parent obj) {
        System.out.println("The value of " + name + " is " + obj.getValue());
        System.out.println("  (PS: " + name + " is a " 
            + obj.getClass().getName() + ")");
    }

    /**
     * Report that it's OK to call this method with this object as an argument
     *
     * @param obj the object that was passed to this method (duh!)
     */
    public static void doThis(Child1 obj) {
        System.out.println("doThis works for a " + obj.getClass().getName());
    }

}

