본문 바로가기

Java/Chapter 15. 클래스 상속 2 : 오버라이딩

[Java] 15.03 - instanceof 연산자

들어가며

 끝으로 유용하게 사용할 수 있는
상속과 관련된 연산자 하나를
소개하고자 한다.

 이 연산자의 피연산자는 참조변수와
클래스의 이름이다.

 

instanceof 연산자의 기본

 연산자 instanceof는 참조변수가 참조하는
인스턴스의 '클래스'나

 참조하는 인스턴스가 '상속하는 클래스'를
묻는 연산자이다.

 예를 들면 다음과 같이 문장을 구성할 수 있다.

if (ca instanceof Cake)
    ....

 위에서 ca는 참조변수이고 Cake는
클래스 이름이다.

 그리고 ca가 참조하는 인스턴스가
Cake의 인스턴스이거나

 Cake를 상속하는 클래스의 인스턴스이면
true를, 그렇지 않다면 false를 반환한다.

 관련하여 다음 예제를 보자.

class Cake {}

class CheeseCake extends Cake {}

class StrawberryCheeseCake extends CheeseCake {}

class EatCakeOf {
    public static void main(String[] arg) {
       Cake cake = new StrawberryCheeseCake();

       if(cake instanceof Cake) {
           System.out.println("Cake instance or");
           System.out.println("instance inherited by Cake \n");
       }

        if(cake instanceof CheeseCake) {
            System.out.println("Cake instance or");
            System.out.println("instance inherited by Cake \n");
        }

        if(cake instanceof StrawberryCheeseCake) {
            System.out.println("Cake instance or");
            System.out.println("instance inherited by Cake \n");
        }
    }
}

/* 실행 결과
Cake instance or
instance inherited by Cake 

Cake instance or
instance inherited by Cake 

Cake instance or
instance inherited by Cake 
*/

 예제에서 선언된 참조변수 Cake가
참조하는 인스턴스는

 StrawberryCheeseCake 인스턴스다.

 그런데 이 인스턴스의 클래스는 Cake를
상속하는 Cake를 상속하는 CheeseCake를
상속한다.

 따라서 위 예제에서 등장하는 3개의
if문의 조건은 모두 true이다.

 

instanceof 연산자의 활용

 다음과 같이 클래스가 정의되어 있는
상황을 고려해보자.

class Box{
    public void simpleWrap() {}
}

class PaperBox extends Box{
    public void paperWrap() {}
}

class GoldPaperBox extends PaperBox {
    public void goldWrap() {}    
}

  그리고 위 클래스들의 인스턴스를
대상으로 하는

 다음 메소드를 정의한다고 가정하자.

public void wrapBox(Box box) {
    ....
}

 위에서 정의한 세 클래스의 인스턴스
모두 위 메소드의 인자로 전달될 수 있다.

 따라서 위의 메소드를 다음과 같이
정의하고자 한다.

public void wrapBox(Box box) {
    // box가 Box 인스턴스를 참조하면, simpleWrap 메소드 호출
    // box가 PaperBox 인스턴스를 참조하면, paperWrap 메소드 호출
    // box가 GoldPaperBox 인스턴스를 참조하면, goldWrap 메소드 호출
}

 이와 같이 참조변수가 참조하는
인스턴스에 따라서

 호출하는 메소드를 달리하는 코드를
작성하는 일은 간단하지 않다.

 그러나 instanceof 연산자를 활용하면
비교적 쉽게 이러한 코드를 작성할 수 있다.

 다음 예제에서 보여주듯이 말이다.

class Box{
    public void simpleWrap() {
        System.out.println("Simple Wrapping");
    }
}

class PaperBox extends Box{
    public void paperWrap() {
        System.out.println("Paper Wrapping");
    }
}

class GoldPaperBox extends PaperBox {
    public void goldWrap() {
        System.out.println("Gold Wrapping");
    }
}

class Wrapping {
    public static void main(String[] args) {
        Box box1 = new Box();
        PaperBox box2 = new PaperBox();
        GoldPaperBox box3 = new GoldPaperBox();

        wrapBox(box1);
        wrapBox(box2);
        wrapBox(box3);
    }

    public static void wrapBox(Box box) {
        if (box instanceof GoldPaperBox)
            ((GoldPaperBox)box).goldWrap();    // 형 변환 후 메소드 호출
        else if (box instanceof PaperBox)
            ((PaperBox)box).paperWrap();       // 형 변환 후 메소드 호출
        else
            box.simpleWrap();
    }
}

/* 실행 결과
Simple Wrapping
Paper Wrapping
Gold Wrapping
*/

 연산자 instanceof는 참조변수가
참조하느 인스턴스의 '클래스'나

 참조하는 인스턴스가 '상속하는
클래스'를 묻는 연산자이므로

 다음과 같이 이 연산자를 이해해도 된다.

 연산자 instanceof는 명시적 형 변환의 가능성을 판단해주는 연산자이다.


 예를 들어서 다음 if문의
연산 결과가 true이면,

if (box instanceof GoldPaperBox) {....}

 이는 box가 참조하는 인스턴스가
GoldPaperBox 인스턴스 이거나

 GoldPaperBox를 상속하는 클래스의
인스턴스라는 뜻으로,

 다음과 같이 명시적으로 형 변환을
할 수 있다.

그렇게 명시적 형 변환을 하여, 형 변환된 인스턴스의 메소드를 호출할 수 있다.
if (box instanceof GoldPaperBox)
    ((GoldPaperBox)box).goldWrap();

참고 및 출처

윤성우의 열혈 Java 프로그래밍
국내도서
저자 : 윤성우
출판 : 오렌지미디어 2017.07.05
상세보기