Java, Object 다형성

Object 클래스는 모든 클래스의 부모이다. 또한 Object 클래스의 기능을 편리하게 제공하기 위해 모든 객체를 참조 할 수 있다.

예제에서 Cat, Car 아무런 상속 관계가 아닌 클래스를 만들어 살펴본다.

Car.java

public class Car {
    public void move() {
        System.out.println("car move");
    }
}

Cat.java

package object;

public class Cat {
    public void sound() {
        System.out.println("cat sound");
    }
}

ObjectPolyMain.java

package object;

public class ObjectPolyMain {
    public static void main(String[] args) {
        Cat cat = new Cat();
        Car car = new Car();

        action(cat);
        action(car);

        // Object 변수에 다른 클래스를 담을 수 있다.
        Object catObj = new Cat();
        Object carObj = new Car();
        
        action(cat);
        action(car);

    }

    private static void action(Object obj) {
        // obj.move(); // 컴파일 오류, Object 타입에는 move 가 없다.
        // obj.sound(); // 컴파일 오류, Object 타입에는 sound 가 없다.

        // move, sound 메소드 호출에는 다운 캐스팅 필요.
        if (obj instanceof Car car) {
            car.move();
        }
        if (obj instanceof Cat cat) {
            cat.sound();
        }
    }
}

출력 결과

cat sound
car move
cat sound
car move

다형적 참조로 Object 타입이 Cat, Car 클래스를 담는 모습을 볼 수 있었다.

// Object 변수에 다른 클래스를 담을 수 있다.
Object catObj = new Cat(); // Cat -> Object
Object carObj = new Car(); // Car -> Object

Object 다형성의 장점?

예제의 action(Object obj) 메소드 분석이 필요하다.
이 메소드는 Object 타입의 매개변수 obj 변수로 받고 있다. 그래서 어떤 객체든지 인자로 받을 수 있다.

action(cat) // main 에서 전달하기
void action(Object obj) // 전달 받은 cat 클래스 Object 변수로 참조하기

Object 다형성의 한계

앞에서 action() 메소드안에서 obj.sound 를 호출하면 오류가 발생하였다. obj 는 Object 타입으로 sound(), move() 메소드가 없고, 자식클래스를 찾지 않는다.

void action(Object obj) {
    // obj.move(); // 컴파일 오류, Object 타입에는 move 가 없다.
    // obj.sound(); // 컴파일 오류, Object 타입에는 sound 가 없다.
}

obj.move() 호출을 받았으나 Object 클래스는 Car 타입의 move() 메소드를 찾지 않는다.

Object 다형성의 한계 극복 - 다운 캐스팅

앞서 말한 한계점으로 sound(), move() 메소드를 호출할 수 없었다.
하지만 다운캐스팅을 사용하면 Cat 타입 또는 Car 타입을 참조하여 직접 호출할 수 있는 방법이 있다.

// move 메소드 다운 캐스팅으로 호출
if (obj instanceof Car car) {
    car.move();
}
  • Object obj 참조 값을 Car car 변수로 다운 캐스팅하여 전달한다.
  • car.move() 호출하여 Car 타입에서 move() 찾아 호출한다.

Object 다형성의 정리

  • Object 모든 객체에게 다형적 참조를 할 수 있다.
  • Object 타입으로 전달 받은 객체를 호출하려면 객체에 맞는 다운캐스팅 과정이 필요

Object 클래스로 활용한 다형성에는 한계가 있다.
Object 클래스는 다형적 참조를 할 수 있으나, 개발자가 임의로 만든 메소드가 정의되어 있지 않아 car.move() 메소드를 호출할 수 없다.
객체의 메소드를 호출하려면 다운캐스팅 과정이 필요하고, 구체적인 객체의 타입을 코드에서 내재되어야 한다.
결국, Object 다형성 활용은 다형적 참조만 가능하고, 메소드 오버라이딩이 지원이 안되어서 그렇다.

다형성을 적극적으로 활용하려면 추상화로 다형적 참조 + 메소드 오버라이딩을 함께한다.