[Java] 자바 - 다형성의 이해 (형변환 및 instanceof 연산자)
자바 - 다형성의 이해 및 예제
자바 다형성(polymorphism)은 객체지향언어의 특징 중 하나입니다. 자바에서 하나의 객체나 메소드가 여러형태로 사용될 수 있는 다형성의 특징을 잘 알고 있지 않으면 시간이 지날수록 미궁에 빠지게 됩니다. 특히 자동 형변환 등 코딩의 편리성을 위해서 제공되는 기능들로 인해서 프로그램 실행은 문제없이 지나갈 수 있으나, 프로그램 소스코드를 가만히 들여다 보면 왜 이렇게 동작되는지 이해가되지 않을 수 있습니다. 여기에서는 이러한 다형성에 대한 개념과 예제를 살펴보도록 하겠습니다.
목차
- 다형성이란?
- 형변환(Casting) 및 사용예제
- 형변환(Casting)의 장점 및 instanceof 연산자
1. 다형성이란?
다형성이란 하나의 객체나 메소드가 여러가지 다른 형태를 가질 수 있는 것을 말합니다.
자바에서 다형성을 나타내는 것으로는, 오버라이딩과 오버로딩 그리고 상속받은 객체의 참조변수 형변환등이 있으며, 여기에서는 예제를 통해서 상속받은 객체의 참조변수 형변환에 대해서 알아보도록 하겠습니다.
cf) 오버로딩과 오버라이딩에 대해서는 아래글을 참고하세요
2022.06.27 - [IT 개발/Java] - [Java] 자바 - 오버로딩과 오버라이딩 (Overloading vs Overriding)
2. 형변환(Casting) 및 사용예제
상속받은 객체에 대해서 형변환이 의미하는 것은, 객체에 속한 멤버들에 대한 사용범위가 달라진다는 것을 의미합니다.
- 업캐스팅(upcasting) : (자식클래스의 인스턴스에 대한) 자식클래스의 타입의 레퍼런스 변수를 부모클래스 타입으로 형변환 하는 것. (타입변환 구문 생략 가능, 자동 형변환 됨)
- 다운캐스팅(downcasting) : (자식클래스의 인스턴스에 대한) 부모클래스 타입의 레퍼런스 변수를 자식클래스 타입으로 형변환 하는 것. (타입변환 구문 생략 불가, 형변환 타입을 명시해야됨)
1) Person 클래스 정의 (부모클래스)
public class Person {
String name;
int age;
public void speak() {
System.out.println(name + ": 안녕하세요");
}
}
2) Dancer 클래스 정의 (자식클래스)
public class Dancer extends Person {
public void dance() {
System.out.println(name + ": 춤을 춥니다");
}
}
3) 객체 생성 및 실행
public class HelloWorld {
public static void main(String[] args) {
//==================================
System.out.println("==== 예시1 ====");
//==================================
Person p1 = new Dancer();
p1.name = "홍길동";
p1.speak();
// p1.dance(); // 사용불가
Dancer d1 = (Dancer) p1; // 다운캐스팅
d1.name = "이순신";
d1.speak();
d1.dance();
//==================================
System.out.println("==== 예시2 ====");
//==================================
Dancer d2 = new Dancer();
d2.name = "제갈공명";
d2.speak();
d2.dance();
Person p2 = (Person) d2; // 업캐스팅 - (Person) 생략가능
p2.name = "신사임당";
p2.speak();
// p2.dance(); // 사용불가
}
}
4) 실행결과
==== 예시1 ====
홍길동: 안녕하세요
이순신: 안녕하세요
이순신: 춤을 춥니다
==== 예시2 ====
제갈공명: 안녕하세요
제갈공명: 춤을 춥니다
신사임당: 안녕하세요
3. 형변환(Casting)의 장점 및 instanceof 연산자
1) 형변환(Casting)의 장점
형변환의 장점으로는 여러 자식클래스 타입의 레퍼런스 변수들을 하나의 부모클래스 타입의 레퍼런스 변수로 다룰수 있다는 것입니다.
만약 아래와 같이 Person이라는 부모클래스를 가진 자식클래스 Dancer, Singer, Actor가 있을 경우, 부모클래스 타입으로 형변환하여 사용하게 되면 아래와 같은 장점이 있습니다.
- 여러 자식클래스 객체를 하나의 배열로 다룰수 있습니다.
- 메소드의 매개변수를 부모클래스 타입 하나로 전달받아 사용할 수 있습니다.
2) instanceof 연산자
앞서 형변환의 장점대로 부모클래스 타입으로 형변환하여 사용하게 되면, 실제 생성된 인스턴스는 여러 자식클래스 중에 어느 것인지 알아야 하는 경우가 생깁니다.
이때 사용할 수 있는 연산자가 instanceof 연산자입니다.
instanceof 연산자는 해당 레퍼런스 변수가 형변환이 가능한지 여부를 확인할 때 사용합니다.
- 사용법 : 레퍼런스변수 instanceof 클래스명
- 반환값 : 형변환 가능하면 true, 아니면 false 반환
(1) 클래스 정의
- 부모클래스 : Person
- 자식클래스 : Dancer, Actor
public class Person { }
class Dancer extends Person { }
class Actor extends Person { }
(2) 객체 생성 및 실행
public class HelloWorld {
public static void main(String[] args) {
Dancer d1 = new Dancer();
Person p1 = (Person) d1;
System.out.println("Person? " + (p1 instanceof Person));
System.out.println("Dancer? " + (p1 instanceof Dancer));
System.out.println("Actor? " + (p1 instanceof Actor));
}
}
(3) 실행결과
Person? true
Dancer? true
Actor? false