[Java] 업캐스팅, 다운캐스팅, instanceof

2020. 4. 27. 19:27Programming Languages/Java

캐스팅이란?

캐스팅(casting) : 타입 변환을 의미한다.

클래스에 대한 캐스팅 - 업캐스팅(upcasting), 다운캐스팅(downcasting) 2가지가 있다.

 

업캐스팅

서브 클래스의 객체에 대한 레퍼런스를 슈퍼 클래스 타입으로 변환하는 것이다.

> 서브 클래스는 슈퍼 클래스를 상속받았기 때문에, 서브 클래스의 객체는 슈퍼 클래스의 멤버를 모두 가진다는 점에서 서브 클래스의 객체를 슈퍼 클래스의 객체로 취급할 수 있다.

Person p; // 상속받은 레퍼런스 p
Student s = new Student(); // Student 객체 생성, 레퍼런스 s 생성
p = s; // 슈퍼 클래스 레퍼런스 p는 서브 클래스 s의 레퍼런스를 가진다. 하지만 p의 멤버에만 접근가능하다.

업캐스팅한 레퍼런스로는 슈퍼 클래스의 멤버에만 접근 가능하다.

그리고 명시적인 형변환을 하지 않아도 된다. 

이것은 결국 두 레퍼런스 변수가 하나의 같은 객체를 가리킨다.

 

업캐스팅을 사용하는 이유

그렇다면 왜 굳이 업캐스팅을 사용해야 할까? 객체를 여러 개 생성하면 되지 않을까?

그 이유는 객체지향 언어의 다형성과 관련이 있다. 아래 코드를 보자.

class Person {
    public void firstname() {
    //...
    }
}

class Kim extends Person {
    public void firstname() { //오버라이딩
    // 성은 김입니다.
    }
}

class Jeung extends Person {
    public void firstname() { //오버라이딩
    // 성은 정입니다.
    }
}

class Name {
    public void naming(Person 어떤 성) { // Person 타입의 변수 어떤 성
    	어떤 성.firstname(); // 어떤 성이 가리키는 객체의 firstname() 실행
    }
}

public class CastingExample {
    public static void main(String[] args) {
    	Name parent1 = new Name();
        Person 성 = new Kim(); // 성은 Kim의 레퍼런스를 가진다.
        parent1.naming(성); // parent1의 naming은 김씨 성을 가진다.
    }
}

만약 업캐스팅을 사용하지 않고 각각의 객체의 메소드를 호출한다면 어떨까?

아래 코드처럼 성이 김씨인지 정씨인지 조건문을 추가한 후에 각 조건에 맞는 객체의 메소드가 호출될 것이다.

pubic void naming(Person 어떤 성) {
    if(Kim?) {
    	Kim.firstname();
    }
    else if(Jeong?) {
    	Jeong.firstname();
    }
    // 박, 이, 장... 성을 추가한다면? 끔찍하다.
}

이처럼 업캐스팅은 다형성의 원칙을 지키는 방법이다. 위 예제에서 성씨 정하는 메소드를 호출할 때는 성이 김이든 정이든 성만 넘겨주면 부모님은 성만(별도의 검사 없이) 결정하면 된다.

 

다운캐스팅

업캐스팅과 반대되는 개념으로, 업캐스팅된 레퍼런스를 다시 원래대로 돌리는 것이다. 이때는 명시적인 형변환을 해줘야 한다. 왜냐하면 부모를 상속 또는 구현한 클래스는 여러 타입이 존재할 수 있기 때문이다.

Person p = new Student("신라면"); // 업캐스팅. p의 레퍼런스는 Student 레퍼런스를 가리킨다.
Student s = (Student)p; // 다운캐스팅. Student 레퍼런스 s는 student p의 레퍼런스를 가리킨다.

 

Instanceof 연산자

Person p = new Person();
Person p = new Student(); // 업캐스팅
Person p = new Researcher(); // 업캐스팅
Person p = new Professor(); // 업캐스팅

만약 위처럼 Person 타입의 레퍼런스 p가 있을 때, p를 사용하려고 보면 p가 어떤 객체를 가리키는지 알기가 복잡해질 경우가 생길수도 있다. 아는 것은 Person을 상속받은 객체가 p로 업캐스팅되었다는 것이다. 그러므로 p를 사용하려면 p가 가리키는 객체가 어떤 클래스의 객체인지 구별할 방법이 필요하다. 이 때 사용하는 것이 Instanceof 연산자다. 아래와 같은 방법으로 사용한다.

 

레퍼런스 instanceof 클래스명 

 

instanceof의 결과값은 boolean값으로, 레퍼런스가 가리키는 객체가 해당 클래스 타입의 객체이면 true, 아니면 false로 계산한다.

주의할 점은 이 연산자는 클래스에만 적용되므로 클래스명에 레퍼런스 변수를 입력하면 안된다.

'Programming Languages > Java' 카테고리의 다른 글

[Java] 추상 클래스  (0) 2020.05.01
[Java] 메소드 오버라이딩(method overriding)  (0) 2020.04.27
[Java] 상속과 생성자  (0) 2020.04.21
[Java] 상속과 접근 지정자  (0) 2020.04.21
[Java] 상속(extends)  (0) 2020.04.21