Java

2024.04.24 다형성(Polymorphism)

정훈5 2024. 4. 24. 11:14
학습 목표 

1. 다형성에 대한 개념을 이해하자. 
2. 업캐스팅과 다운캐스팅이란?
3. 다형성에 활용

 

다형성에 대한 개념을 이해하자.

다형성은 하나의 데이터 타입이 다양한 형태로 바라볼 수 있는 것  --> ex) '배'  :  사람신체의 '배', 바다에 떠다니는 '배'

다형성(Polymorphism)은 객체 지향 프로그래밍에서 중요한 개념 중 하나입니다.

이는 한 요소(예: 메서드, 클래스)가 여러 형태를 가질 수 있는 능력을 의미합니다.

다형성은 코드의 유연성과 재사용성을 높여주며, 상속, 추상화, 인터페이스와 함께 사용됩니다.

 

시나리오 코드 1

 package basic.ch20;

public class Animal {
	
	public void move() {
		System.out.println("동물이 움직입니다.");
	} // 메서드
	
	public void eating() {
		System.out.println("먹이를 먹습니다.");
	} // 메서드
}

 

package basic.ch20;

public class Tiger extends Animal {
	
	@Override
	public void move() {
		// 재 정의
		System.out.println("호랑이가 네발로 걸어요");
	}
	
	@Override
	public void eating() {
		// 재 정의
		System.out.println("호랑이가 사냥을 합니다.");
	} // Animal 메서드 상속
}
package basic.ch20;

public class Human extends Animal {
	
	@Override
	public void move() {
		// 재 정의
		System.out.println("사람이 두 발로 걷습니다.");
	}
	
	@Override
	public void eating() {
		// 재 정의
		System.out.println("밥을 먹습니다.");
	}
	
	public void readBooks() {
		System.out.println("책을 읽습니다.");
	}

}

 

package basic.ch20;

public class AnimalTest {

	public static void main(String[] args) {
		
		Animal animal = new Animal();
		animal.move();
		animal.eating();
		System.out.println("-----------------------");
		
		Animal 주소2 = new Tiger(); // Tiger은 Animal 타입으로 바라볼 수 있다.
		주소2.move(); 
		주소2.eating();
		System.out.println("-----------------------");
		
		Animal 주소3 = new Human(); // 주소3 에는 Human() 주소가 들어간다.
		주소3.move();
		주소3.eating();
		// 컴파일 시점의 오류
		 // 주소3.readBooks();

	} // end of main

} // end of class

업캐스팅과 다운캐스팅이란?

업캐스팅(Upcasting)다운캐스팅(Downcasting)은 객체 지향 프로그래밍에서 다형성을 활용할 때 사용되는 개념

업캐스팅(Upcasting)

Animal animal = new Dog(); // 업캐스팅
  • 업캐스팅은 부모 클래스의 참조 변수로 자식 클래스의 객체를 참조하는 것을 말합니다.
  • 부모 클래스의 데이터 타입으로 자식 클래스의 객체를 대입하는 것을 의미합니다.
  • 업캐스팅은 자동으로 이루어집니다.
package basic.ch20;

public class AnimalTest {

	public static void main(String[] args) {
		
		Animal animal = new Animal();
		animal.move();
		animal.eating();
		System.out.println("-----------------------");
		
		Animal 주소2 = new Tiger(); // Tiger은 Animal 타입으로 바라볼 수 있다.
		주소2.move(); 
		주소2.eating();
		System.out.println("-----------------------");
		
		Animal 주소3 = new Human(); // 주소3 에는 Human() 주소가 들어간다.
		주소3.move();
		주소3.eating();
		// 컴파일 시점의 오류가 발생한다. -> Human() 메서드를 사용 할 수 없다.
		// 다운캐스팅 필요? **
		 // 주소3.readBooks();
		
		// 다운캐스팅 
		( (Human)주소3 ).readBooks();
		System.out.println("--------------------------");
		
	} // end of main

} // end of class

 

 

다운캐스팅(Downcasting)

Animal animal = new Dog(); // 업캐스팅
Dog dog = (Dog) animal; // 다운캐스팅
  • 다운캐스팅은 부모 클래스의 참조 변수를 자식 클래스의 객체로 변환하는 것을 말합니다.
  • 다운캐스팅은 명시적으로 형변환을 해야 합니다.
  • 다운캐스팅은 업캐스팅된 객체가 실제로 자식 클래스의 객체일 때만 가능합니다. 그렇지 않으면 ClassCastException(예외) 이 발생할 수 있습니다.
package basic.ch20;

public class FruitTest {
	// Code Start
	public static void main(String[] args) {

		// 다형성
		// 다양한 형태로 클래스(데이터 타입을) 바라볼 수 있다.

		Fruit fruit1 = new Banana(); // 업 캐스팅 된 상태이다.
		// 부모 클래스의 참조 변수로 자식 클래스의 객체를 참조

		Fruit fruit2 = new Peach(); // 업 캐스팅 된 상태이다.
		// 부모의 클래스를 참조 변수로 자식 클래스의 객체를 참조
		

		fruit1.showInfo();
		fruit2.showInfo();
		
		System.out.println("------------------------");

		// 다형성을 사용하면 코드를 유연하게 작성할 수 있다.

		Banana banana1 = new Banana(); 

		Peach peach1 = new Peach();
		Peach peach2 = new Peach();

		Fruit[] fruits = new Fruit[3];
		fruits[0] = banana1;
		fruits[1] = peach1;
		fruits[2] = peach2;
		System.out.println(fruits[1].name);
		
		System.out.println("-------------------------------");
		
		// fruits[0] --> 바나나
		// 바나나에 속성인 origin 을 출력하시오
		// 바나나에 기능인 saleBanana() 메서드를 호출하시오.
		
		// Banana bananaCasting = (Banana)fruits[0];
		// ((Banana)fruits[0]).origin;
		System.out.println( ((Banana)fruits[0]).origin );
		((Banana)fruits[0]).saleBanana();
		
		System.out.println("--------------------");
		
		// 0 --> 바나나
		// 1 --> 복숭아
		
		// instanceof 연산자를 알고 있어야 해결 가능
		
		// infstanceof -->
		// 실행 시점에 객체가 특정 클래스의 인스턴스인지 확인하는 키워드
		for(int i=0; i<fruits.length; i++) {
			if(fruits[i] instanceof Banana) {
			((Banana)fruits[i]).saleBanana();
			} else {
				fruits[i].showInfo();
			}	
		}
		
	} // end of main

} // end of class

 

정리

● 하나의 코드가 여러 자료형으로 구현되어 실행되는 것

● 같은 코드에서 여러 다른 실행 결과가 나옴

● 정보은닉, 상속과 더불어 객체지향 프로그래밍의 가장 큰 특징 중 하나임

● 다형성을 잘 활용하면 유연하고 확장성있고, 유지보수가 편리한 프로그램을 만들수 있음

 

package starcraft.ver04;

/*
 * 접근 제어 지시자
 * 
 * public
 * protected -- 상속관계 설정할 수 있다.
 * default
 * private
 */
public class Unit {

	protected String name;
	protected int power;
	protected int hp;

	public Unit(String name) {
		this.name = name;
	} // 생성자

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getPower() {
		return power;
	}

	public void setPower(int power) {
		this.power = power;
	}

	public int getHp() {
		return hp;
	}

	public void setHp(int hp) {
		this.hp = hp;
	}
	 

	// 자신이 공격을 당합니다.
	public void beAttacked(int power) {
//				hp = hp - power;
		// 방어적 코드 작성
		// 80 -- 72 == 5
		// 5 - 75 == -70
		if (hp <= 0) {
			System.out.println("[" + this.name + "]" + "이미 사망하였습니다.");
			hp = 0; // 체력이 0 밑으로 출력되는 것을 막기위해 0 으로 지정함
			return; // 함수 종료
		}
		hp -= power;
	}

	// 질럿을 공격한다.
	public void attack(Unit z) {
		System.out.println(this.name + " 이 " + z.getName() + " 을 공격합니다.");
		z.beAttacked(power);
	}

	public void showInfo() {
		System.out.println("==== 상태창 ====");
		System.out.println("이름 : " + this.name);
		System.out.println("공격력 : " + this.power);
		System.out.println("생명력 : " + this.hp);
	}

}