본문 바로가기

Programming/JAVA

상속(11) - 객체의 타입 확인(instanceof)

java logo image

 

 

우리는 앞선 아티클에서, 다소 머리는 아팠지만 자식 클래스 타입의 객체를 부모 클래스 타입 객체로 강제 타입 변환을 진행하는 과정을 살펴보았습니다. 여기서, 당연한 이야기를 하나 하자면 "순수 부모 클래스 타입의 객체"는 자식 클래스 타입의 객체로 강제 타입 변환이 불가능합니다. 아래와 같은 경우를 의미하죠.

 

Parent parent = new Parent();
Child child = (Child) parent; // 불가능

 

반복되는 얘기지만, 부모 클래스의 경우에는 자식 클래스 고유의 속성들을 갖고 있지 않기 때문에 이런 변환은 불가능합니다. 자, 그럼 어떤 코드를 설계하는 과정에서, "부모 클래스 타입의 변수"가 있다고 가정하고 이를 캐스팅(casting)할 때 우리는 한 가지를 주의해야 합니다. 바로 그 부모 클래스 타입의 변수가 위에서 말한 "원래는 자식 클래스 타입인 변수"인지를 확인해야 하는 것이죠. 파라미터 인자 값이나 특정 변수가 부모 클래스 타입의 변수라서 캐스팅을 시도했는데, 코드를 헷갈려서 "순수 부코 클래스 타입의 변수"를 자식 클래스 타입으로 캐스팅하면 예외가 발생하기 때문이지요.

 

 

 


 

 

 

이럴 때 사용하는 연산자가 하나 있습니다. 바로 연산자 instanceof죠. 이 연산자는 특정 객체가 우리가 지정해 주는 타입의 객체가 맞는지 여부를 검사하고 boolean 값을 리턴해줍니다. 코드로 구현하면 아래와 같습니다. 

 

boolean result = 객체 instanceof 타입;

// parent가 원래는 Child 타입인 객체인지 확인
boolean result = parent instanceof Child;

 

위와 같이 Parent 타입인 변수 parent가 사실은 Parent의 자식 클래스인 Child 클래스 타입인지를 확인하게 되고 맞다면 true, 아니라면 false를 리턴하게 되는 것입니다. 

 

이 instanceof 연산자는 주로 메서드 파라미터에서 특정 인자 값을 받은 다음, 메서드 안에서 캐스팅이 일어나는 경우에 안전장치로 사용하게 됩니다. 즉, 캐스팅이 가능한 변수라면 진행하고 아니면 캐스팅을 진행하지 않음으로써 예외를 방지하는 것이죠. 이 역시 간단히 예를 들어 보겠습니다. 

 

public void method(Parent parent) {
	if(parent instanceof Child) {
    	Child child = (Child) parent;
    }
}

 

위의 메서드를 보시면, 파라미터에 Parent 타입의 변수가 오도록 되어 있습니다. 여기에는 당연히 Parent 타입이 올 수도 있고, 우리가 자동 타입 변환 아티클에서 배웠듯이 Parent를 상속받는 Child 타입의 객체가 들어와서 자동 타입 변환이 일어난 경우일 수도 있습니다. 이 파라미터에서 전달받은 인자 값이 Child 타입이 아니라면 캐스팅이 발생하지 않도록 안전장치를 해둔 것을 알 수 있죠?

 

 

상속(9) - 파라미터의 다형성

앞선 아티클에서, 다형성에 대해 살펴보면서 상속받은 자식 클래스의 자동 변환이 일어나는 케이스에 대해서 살펴보았습니다. 이때 주로 인스턴스 생성 과정을 중심으로 다루었고, 결국 '필드'

nozeroslope.tistory.com

 

이제 상세한 예제 코드를 통해서 다시 한번 instanceof의 사용을 익혀보도록 합시다. 

 

 


 

예시에서는 method1은 instanceof를 통해 타입 체크를 진행하고, method2는 타입 체크를 진행하지 않는 경우입니다.

public class Parent {
	
}

 

public class Child extends Parent {

}

 

public class ExampleMain {	
	public static void method1(Parent parent) {
		if(parent instanceof Child) {
			Child child = (Child) parent;
			System.out.println("method1 - Child 캐스팅 성공");
		} else {
			System.out.println("method1 - Child 캐스팅 실패");
		}
	}
	
	public static void method2(Parent parent) {
		Child child = (Child) parent;
		System.out.println("method1 - Child 캐스팅 성공");
	}
	
	public static void main(String[] args) {
		Parent parentA = new Child();
		method1(parentA);
		method2(parentA);
		
		Parent parentB = new Parent();
		method1(parentB);
		method2(parentB);
	}
}

/* 출력
method1 - Child 캐스팅 성공
method1 - Child 캐스팅 성공
method1 - Child 캐스팅 실패
Exception in thread "main"...(예외)
*/