다형성은 polymorphism 폴리몰피즘이라고 한다. 일단 의미는 커녕 읽는 것도 어려워 보인다.

 

dictionary.com에서는 아래와 같이 정의한다.

 

* the state or condition of being polymorphous.

- 폴리몰퍼스의 상태, 아래가 폴리몰퍼스의 정의다.

 

* having, assuming, or passing through many or various forms, stages, or the like.

많은 다양한 형태와 스테이지 그 비슷한 성질을 가지고, 추정하고, 겪는다.

 

라는 추상적 의미를 가지고 있다만...

 

컴퓨터 프로그래밍에서는 하나의 요소 (객체,변수,표현식, 함수, 클래스 등)가  다양한 자료형에 속하거나 사용되는 것이 가능하다. 말 그대로 다양한 형태의 성질을 가지고 있다.

 

*예제로 클래스의 다형성을 테스트해보자.

 

그전에 혹시 클래스 형 변환과 가상 메소드 방식이 궁굼하면 아래를 참고한다.

 

자바 튜토리얼 (8-2) 상속 클래스 생성자, super 키워드, 클래스 형변환

상속을 받은 클래스가 인스턴스를 생성할 때 어떤 일이 벌어지는가 알아본다. public class OOPTest { public static void main(String[] args) { B1 b1 = new B1(); System.out.println("Good Day, dear my lord!..

digiconfactory.tistory.com

 

 

자바 튜토리얼 (8-3) 메서드 오버라이딩

1. 오버라이딩 메서드의 오버라이딩이란 무엇인가? 네이버 사전에 따르면, 1) 동사 (직권을 이용하여 결정·명령 등을) 기각[무시]하다 (=overrule) 2) 동사 …보다 더 중요하다[우선하다] 3) 동사 (��

digiconfactory.tistory.com

이번 예제는 게임 캐릭터이다. Human 은 기본 종족이고 Fighter 와 Wizard, Kinght, Monk 는 기본 종족을 상위클래스로 한다. 클래스를 하나씩 만드는 것은 어렵지 않다. 똑같은 형식을 반복하고, 각 종족의 특성에 맞는 내용만 작성한다.

 

실행하는 class는 OOPTest3이다. 여기에 메소드가 주요하다.

 

public void commonAttack(Human human){

   human.attack();

}

 

클래스의 형변환(묵시적, 하위 인스턴스를 상위클래스 자료형으로 참조하는 것)과 메소드 오버라이드를 활용한다. 각 하위클래스에 메소드 오버라이드를 시켜준다.

 

Human 계열이 상위 클래스 자료형이므로 new Fighter( ) 같은 하위 인스턴스를 참조시키는게 가능하다.

 

opt1.commonAttack(new Fighter()); 처럼 사용해도 되고 인스턴스 변수를 만들어서 넘겨줘도 된다. 여기서는 new 키워드만 사용한다.

 

public class OOPTest3 {
	public static void main(String[] args) {
		OOPTest3 opt1 = new OOPTest3();
		
		/* Alternative way
		Fighter ft1 = new Fighter();
		opt1.commonAttack(ft1);
		*/
		
		opt1.commonAttack(new Fighter());
		opt1.commonAttack(new Wizard());
		opt1.commonAttack(new Knight());
		opt1.commonAttack(new Monk());
		
		System.out.println("---------------------------------");
		System.out.println("Dear my friend, Hasiri Tsuzukete!");
		System.out.println("=================================");
	}
	public void commonAttack(Human human) {
		human.attack();
	}
}
class Human{
	public void attack() {
		System.out.println("Human's attack!");
	}
}
class Fighter extends Human{
	public void attack() {
		System.out.println("Fighter's axe attack!");
	}
}
class Wizard extends Human{
	public void attack() {
		System.out.println("Wizard's magic missile attack!");
	}
}
class Knight extends Human{
	public void attack() {
		System.out.println("Knight's sword attack!");
	}
}
class Monk extends Human{
	public void attack() {
		System.out.println("Monk's jump kick attack!");
	}
}

결과

결과는 하위클래스의 오버라이드된 메서드들이 실행되었다. 만약 Human 의 attack도 같이 실행시키고 싶다면 super.attack( ) 을 상위 클래스의 메소드를 호출할 수 있다.

 

main 클래스의 human.attack( ) 코드는 변하지 않지만 거기에 어떤 인스턴스를 매개변수로 넣느냐에 따라서 다양하게 바뀌는 성격을 갖는다. 이것이 다형성이다.

 

새로운 직업 예를 들어 궁수나 창병을 추가 시킨다면 Human 클래스를 상속받아 구현하면 쉽게 관리가 된다. 다형성의 뜻은 복잡하지만 다형성이 추구하는 것은 코드의 양도 줄면서, 관리가 쉽고 확장이 좋은 프로그램이다.

 

* ArrayList 배열 사용법

ArrayList 클래스로 다형성을 더 쉽게 사용하는 방법이다. ArrayList는 import java.util.ArrayList 로 임포트 해야 사용가능하다. 

 

ArrayList<Human> : 약간 생소한 문법인데 상위클래스 Human 형의 자료형으로 배열을 만든다. 개수는 넣지 않아도 된다.

 

다음 줄에서 업캐스팅 (클래스 형 변환) 을 한다. ArrayList 인스턴스에 Human 형을 다 추가한다.

 

for(Human hm1 : hl1) 

 

이 문법은 파이썬의 그것들과 좀 유사하다. for i in range(10)

 

hl1의 객체배열에 저장되어 있는 요소들을 다 꺼낼때까지 루프한다. 요소의 개수는 4개이다. 그러니까 4번 루프한다. 상위 클래스 참조에서 각각 인스턴스에 맞게(Fighter, Wizard 등) 가상메서드를 호출한다. (오버라이드 된 메서드들)

public class OOPTest3 {
	public static void main(String[] args) {
		
		ArrayList<Human> hl1 = new ArrayList<Human>();
		
		Human human1 = new Fighter();
		Human human2 = new Wizard();
		Human human3 = new Knight();
		Human human4 = new Monk();
		
		hl1.add(human1);
		hl1.add(human2);
		hl1.add(human3);
		hl1.add(human4);
		
		System.out.println("==== Class Test ====");
		for (Human hm1 : hl1) {
			hm1.attack();
		}

		
		System.out.println("---------------------------------");
		System.out.println("Dear my friend, Hasiri Tsuzukete!");
		System.out.println("=================================");
	}
}
class Human{
	public void attack() {
		System.out.println("Human's attack!");
	}
}
class Fighter extends Human{
	public void attack() {
		System.out.println("Fighter's axe attack!");
	}
}
class Wizard extends Human{
	public void attack() {
		System.out.println("Wizard's magic missile attack!");
	}
}
class Knight extends Human{
	public void attack() {
		System.out.println("Knight's sword attack!");
	}
}
class Monk extends Human{
	public void attack() {
		System.out.println("Monk's jump kick attack!");
	}
}

아까처럼 main 클래스에서 메서드를 만들 필요도 없으니 구조가 군더더기 없이 좋다.

공유하기

facebook twitter kakaoTalk kakaostory naver band