Polymorphism (다형성) : 다양한 형태의 성질
같은 타입이지만 실행결과가 다양한 객체를 이용할 수 있는 성질
코드 측면에서 보면 다형성은 하나의 타입에 여러 객체를 대입함으로써 다양한 기능을 이용할 수 있도록 해준다.
다형성을 위해 자바는 부모 클래스로 타입 변환을 허용해준다.
즉 부모타입에 모든 자식객체가 대입될 수 있고, 이것을 이용하면 객체는 부품화가 가능합니다.
※ 다형성은 동적 바인딩(런타임 때 최종 타입이 결정되는 것)이 지원되어야 한다.
예제 1. 어벤져스
- Hero 클래스를 상속받은 Ironman, Hulk, Spiderman, Thor클래스가 각각의 위치(하늘, 땅, 바다, 우주)를 담은 변수를 갖고, 각기 다른 공격방식(Javis, 주먹, 거미줄, 번개)을 갖도록 하였다.
package polymorphism;
class Hero{
public String name;
public void attack() {
System.out.println("공격");
}
}
class Ironman extends Hero{
public String spot = "하늘";
int suitCount;
public void makeSuit() {
System.out.println("Javis, 슈트 만들어줘.");
}
@Override
public void attack() {
System.out.println("javis, 공격");
}
}
class Hulk extends Hero{
public String spot = "땅";
@Override
public void attack() {
System.out.println("주먹");
}
}
class Spiderman extends Hero{
public String spot = "바다";
@Override
public void attack() {
System.out.println("거미줄");
}
}
class Thor extends Hero{
public String spot = "우주";
@Override
public void attack() {
System.out.println("번개");
}
}
public class Polymorphism {
public static void main(String[] args) {
Hero h1; //컴파일타임
h1 = new Ironman(); //런타임
Hero[] avengers = new Hero[4];
avengers[0] = new Ironman();
avengers[1] = new Hulk();
avengers[2] = new Spiderman();
avengers[3] = new Thor();
for (Hero hero : avengers) {
hero.attack();
}
for (int i = 0; i < avengers.length; i++) {
avengers[i].attack();
}
}
}
[실행결과]
javis, 공격
Javis, 슈트 만들어줘.
Javis, 슈트 만들어줘.
javis, 공격
주먹
거미줄
번개
javis, 공격
주먹
거미줄
번개
※ 컴파일타임, 런타임
Hero h1; //컴파일타임
h1 = new Ironman(); //런타임
※ 자식 객체는 부모 클래스로의 타입 변환을 허용한다.
즉, 부모 객체에 자식 객체를 대입하여 부모 클래스로 타입 변환하는 것은 가능하다. (결과 : 부모)
그러나 자식 객체에 부모 객체를 대입하는 것은 불가능하다.
Hero h = new Ironman(); //가능
Ironman i = new Hero(); //불가능
※ 자식 클래스에서 정의한 멤버나 메소드 사용하기
- 방법1) 형변환
//방법1 형변환
((Ironman)h1).makeSuit(); //Javis, 슈트 만들어줘.
((Ironman)h1).suitCount = 10; //Javis, 슈트 만들어줘.
- 방법2) 새 객체 생성
//방법2 새 객체 생성
Ironman i2 = (Ironman)h1;
i2.makeSuit();
예제 2. 어벤져스2
- 위치에 따라 다른 Hero를 부를 수 있도록 Hero 클래스에 callHero 메소드를 만든다.
package polymorphism;
public class Polymorphism02 {
public static Hero callHero(String spot) {
if(spot.equals("하늘")) {
return new Ironman();
}else if(spot.equals("땅")) {
return new Hulk();
}else if(spot.equals("바다")) {
return new Spiderman();
}else {
return new Thor();
}
}
public static void main(String[] args) {
Hero h1 = callHero("바다"); //바다에 해당하는 영웅은 스파이더맨
Hero h2 = callHero("땅"); //땅에 해당하는 영웅은 헐크
h1.attack(); //거미줄 //스파이더맨의 공격은 "거미줄" 이므로
h2.attack(); //주먹 //헐크의 공격은 "주먹" 이므로
}
}
[실행결과]
거미줄
주먹
※ 참고
Hero 클래스의 callHero 메소드를 선언할 때, Hero 클래스에 직접 가서 callHero 메소드를 정의하지 않고
다음과 같이 Polymorphism02 클래스 안에서 외부 클래스인 Hero 클래스의 callHero 메소드를 선언했다.
package polymorphism;
public class Polymorphism02 {
public static 외부클래스 메소드이름(파라미터) {
...
}
}
어벤져스2 에서는 아래와 같이 사용 되었다.
package polymorphism;
public class Polymorphism02 {
public static Hero callHero(String spot) {
...
}
public static void main(String[] args) {
...
}
}