Upcasting Downcasting Dynamic Binding

Upcasting: 하위 클래스의 객체를 상위 클래스의 객체로 assign하여 변환하는 것

Downcasting: 상위 클래스의 객체를 하위 클래스의 객체로 assign하여 변환하는 것

Dynamic Binding (동적 바인딩):  Dynamic binding is also known as late binding or run-time binding. 동적 바인딩이란 실행시 해당 객체에 맞는 오버라이딩된 메소드가 호출되는 것

// PersonStudentTest
class PersonStudentTest {
    static void print(Object o) {
        System.out.println(o);
    }
    static void print(Person[] arr) {
        for (Person p : arr) System.out.println(p);
    }

    public static void main(String[] args) {
        Person h1 = new Person("JAVA", 2018);
        h1.print();
        print(h1);
        System.out.println(h1);

        Person h2 = new Student(); // upcasting
        h2.print(); // dynamic binding Student.print()
        //print(h2);
        //System.out.println(h2);

        Object o = h2; // upcasting
        ((Student)o).print(); // downcasting o=> Student 
        ((Person)o).print(); // downcasting o=> Person => Person.print() dynamic binding Student.print()

        Person[] pList = new Person[5];
        pList[0] = new Person("JAVA1", 1);
        pList[0].print();
        pList[1] = pList[0];
        pList[1].print();
        pList[2] = new Student(); // upcasting
        pList[2].print(); // dynamic binding Student.print()
        pList[3] = new Student("JAVA2", 2, 222); // upcasting
        pList[3].print(); // dynamic binding Student.print()
        pList[4] = pList[3];
        pList[4].print(); // dynamic binding Student.print()

        System.out.println("AFTER SET");
        pList[0].set("JAVA3", 3); // Person.set(string, int)
        pList[4].set("JAVA4", 4); // Person.set(string, int)
        print(pList);

        System.out.println("AFTER SET2");
        Student s = (Student)pList[4]; // downcasting
        s.set("JAVA5", 5, 555); // Student.set(string, int, int)
        print(pList);

        System.out.println("AFTER SET3");
        pList[0].set(pList[4]); // Person.set(Person)
        print(pList);

        System.out.println("AFTER SET4");
        ((Student)pList[2]).set(pList[4]); // downcasting Student.set(Person)
        //((Student)pList[2]).set((Student)pList[4]); // Student.set(Student)
        print(pList);

        System.out.println("AFTER SET5");
        ((Student)pList[2]).set(new Person("JAVA6", 6)); // downcasting Student.set(Person)
        //((Student)pList[2]).set((Student)pList[4]); // Student.set(Student)
        print(pList);

        Person.printCount(); // calls Person printCount() static method
        Student.printCount(); // calls Student printCount() static method
        System.out.println();
    }
}