본문 바로가기

TIL/☕️ JAVA

About 다형성: 클래스 형변환을 하는 이유

Q1. 부모타입으로 자식객체를 참조하게 되면 부모가 가지고 있는 메소드만 사용할 수 있다. 그런데 형변환을 하는 이유가 무엇일까?

 

부모 타입으로 자식 객체를 참조하면 부모 클래스에 정의된 메소드만 사용할 수 있다. 하지만 때로는 자식 클래스에서 추가로 정의한 메소드나 멤버 변수에 접근해야 할 때가 있다. 이 경우 자식 클래스의 메소드나 멤버 변수에 접근하려면 부모 타입의 참조를 자식 타입으로 형변환해야 한다.

 

예를 들어, 다음과 같은 코드가 있다고 가정해 보자.

class Animal {
    public void move() {
        System.out.println("Animal is moving");
    }
}

class Dog extends Animal {
    public void move() {
        System.out.println("Dog is walking");
    }
    public void bark() {
        System.out.println("Woof!");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal animal = new Dog();
        animal.move();
    }
}

위 코드에서 Animal 클래스에는 move() 메소드가 정의되어 있지만, Dog 클래스에서는 이 메소드를 재정의하고 있다.

따라서 위 코드에서 animal.move()를 호출하면 Dog 클래스에서 재정의한 move() 메소드가 호출된다.

 

그런데 Dog 클래스에는 추가로 bark() 메소드가 정의되어 있다. 위 코드에서는 Animal 타입의 변수 animal을 사용하고 있으므로, 이 변수로는 bark() 메소드에 접근할 수 없다. 이때, Animal 타입의 변수를 Dog 타입으로 형변환하면, bark() 메소드에도 접근할 수 있게 된다.

 

public class Main {
    public static void main(String[] args) {
        Animal animal = new Dog();
        animal.move();
        
        if (animal instanceof Dog) {
            Dog dog = (Dog) animal;
            dog.bark();
        }
    }
}

위 코드에서는 먼저 animal.move()를 호출한다. 이어서, if 문을 사용하여 animal 변수가 실제로 Dog 클래스의 객체인지 확인한다. 이후에, animal 변수를 Dog 타입으로 형변환하여 bark() 메소드를 호출한다.

이렇게 하면 부모 타입으로 참조하더라도 자식 클래스에서 추가로 정의한 메소드나 멤버 변수에 접근할 수 있다.

 

 

 


 

Q2. 위 코드에서 Animal 타입의 변수 animal을 사용하고 있다. 왜 Dog 타입으로 안 하고 Animal 타입으로 정의하는 이유는 무엇일까?

Dog animal = new Dog(); 이렇게 안 하는 이유를 알아보자.

 

Animal 타입의 변수를 사용하는 이유는 다형성(Polymorphism)을 구현하기 위해서이다.

다형성이란,

서로 다른 클래스가 상속 계층에서 상위 클래스와 하위 클래스의 관계를 가지고 있을 때, 하위 클래스의 객체를 상위 클래스의 타입으로 참조할 수 있다는 개념을 말한다.

 

위에서 예로 든 Animal 클래스와 Dog 클래스도 상속 관계를 가지고 있다. 이때, Animal 타입의 변수 animal을 사용하면, 이 변수를 Dog 클래스의 객체로 초기화하더라도, Animal 클래스에서 정의한 메소드만 사용할 수 있다.

 

하지만 Dog 클래스에서 Animal 클래스의 메소드를 오버라이딩(Overriding)했다면, Dog 클래스에서 오버라이딩한 메소드가 호출된다.

 

그리고 Animal 타입의 변수를 사용하면, 이 변수를 다른 하위 클래스의 객체로도 참조할 수 있다.

즉, Animal 타입의 변수는 Animal 클래스를 상속하는 다른 클래스의 객체도 참조할 수 있으므로, 코드의 재사용성과 유연성이 높아진다.

 

Dog animal = new Dog();와 같이 구체적인 클래스 타입으로 변수를 정의하는 것도 가능하다. 이 경우, 해당 변수는 구체적인 클래스의 메소드와 멤버 변수에 모두 접근할 수 있다.

그러나 이 변수는 다른 하위 클래스의 객체를 참조할 수 없으므로, 유연성이 떨어지게 된다. 따라서, 가능하면 상위 클래스 타입의 변수를 사용하는 것이 좋다.

 
 

 

'TIL > ☕️ JAVA' 카테고리의 다른 글

TDD 방식으로 자바 연습하기  (0) 2023.03.12
Equals()와 == 연산자  (0) 2023.03.12
About 다형성: 인터페이스를 사용하는 이유  (0) 2023.03.04
'참조한다'라는 건  (0) 2023.03.03
오버로딩과 오버라이딩 차이  (0) 2023.03.03