본문 바로가기
Back-End/Java

[Java] 다형성(polymorphism)

by 찐코딩 2021. 8. 18.

다형성(polymorphism)

  - 객체지향 프로그램 4대 특징 중 하나. - 상속과 연관성이 많음.
  - 다형성의 사전적 의미 - 같은 종의 생물이지만 모습이나 특징이 고유한 성질을 가지고 있는 것.
  - 여러가지 모습으로 해석될 수 있는 형태를 의미함.
  - 여러가지 형태를 가질 수 있는 능력을 말함.
  - 하나의 메서드나 클래스가 있을 때 이것들이 다양한 방법으로 동작하는 것.
  - 하나의 사물(객체)을 다양한 타입으로 선언하고 이를 이용할 수 있는 성질.
  - 하나의 참조변수로 여러 타입의 객체를 참조할 수 있는 것.
    ==> 부모타입의 참조변수로 자식타입의 객체를 다룰 수 있는 것이 다형성의 특징.
        단, 자식 클래스에서 상속을 받은 멤버들만 접근할 수 있고,
        자식 클래스에서 만들어진 멤버들에는 접근할 수 없음.
        예) 부모타입의 참조변수로 자식의 멤버를 호출.
  - 부모 타입의 참조변수로 자식 타입의 인스턴스를 참조할 수 있지만,
    반대로 자식타입의 참조변수로 부모타입의 인스턴스를 참조할 수는 없음.

 

instanceof 연산자

  - 참조변수가 참조하고 있는 인스턴스의 실제 타입을 알아보는 연산자.
  - 연산결과로  boolean 값(true / false)를 반환.
    예) 참조변수 instanceof 클래스명(타입)
       if(a instanceof Car) : 참조변수 a의 타입이 Car 클래스 타입인지 체크함.
       ==> true이면 Car 인스턴스 타입이고  false이면 Car 인스턴스 타입이 아니다.

 

예시)

package Polymorphism;

class A {}

class B extends A {}

class C extends A {}

class D extends B {}

class E extends C {}

public class Ex04_Main {

	public static void main(String[] args) {
		
		B b = new B();
		C c = new C();
		D d = new D();
		E e = new E();
		
		A b1 = new B();	// B클래스는 A클래스를 상속받았으므로, 변수 b1는 A이다.
		A c1 = new C();	// C클래스는 A클래스를 상속받았으므로, 변수 C1는 A이다.
		A d1 = new D(); // D클래스는 A클래스를 상속받은 B를 상속 받았으므로, 변수 d1는 A이다.
		A e1 = new E(); // E클래스는 A클래스를 상속받은 C를 상속 받았으므로, 변수 e1는 A이다.
		
		B d2 = new D(); // D클래스는 B클래스를 상속 받았으므로, 변수 d2는 B이다.
		C e2 = new E(); // E클래스는 C클래스를 상속 받았으므로, 변수 e2는 C이다.
		
		
		// instanceof : 두 개의 객체가 같은 지 물어보는 연산자
		if(d instanceof B) {
			// 참조변수 d의 타입이 B 클래스 타입인지 체크
			// 맞으면 true 출력
			System.out.println("true"); }
		// 아니면 false 출력
		else {
			System.out.println("false"); }
	}
}

결과

true

예제 01)

다형성을 이용해서 Animal 이라는 추상클래스를 만들고,

이에 강아지, 고양이 등의 자손 타입 클래스를 생성하여 프로그램을 구현하자

package Polymorphism;

interface Animal {
	//추상메소드 구현
	void sound();
}

class Dog implements Animal{

	//부모에서 상속받은 메소드
	@Override
	public void sound() {
		System.out.println("멍멍멍");		
	}
	
	
	//자식의 메소드
	void output() {
		System.out.println("출력용 메소드입니다.");
	}
}


class Cat implements Animal{

	//부모에서 상속받은 메소드
	@Override
	public void sound() {
		System.out.println("냐옹");
	}
}


public class Ex01_Animal {
	
	public static void main(String[] args) {
		
		Dog dog = new Dog();
		dog.sound();
		
		Cat cat = new Cat();
		cat.sound();
		
		// 다형성을 이용하여 객체를 생성
		Animal dog1 = new Dog();	// 강아지(dog)은 동물(Animal)이다. => 업캐스팅
		dog1.sound();
		
		// 자식클래스에서 만들어진 멤버에는 접근 불가
		// 부모에는 없는 자식의 멤버는 호출할 수 없다.
		// dog1.output();     ==> error 발생
		
		Animal cat1 = new Cat();	// 고양이(cat)는 동물(Animal)이다. => 업캐스팅
		cat1.sound();
				
		// 자식에는 있는 멤버가 부모에는 없을 수 있기 때문에 자식이 부모의 객체로는 생성 불가.
		//Dog dog2 = new Animal();		==> error 발생, 동물(Animal)은 강아지(dog)다. 라는 명제가 당연히 거짓인 것 처럼.
	}
}

 


예제02)

다형성을 이용해서 오버워치 게임을 만들어보자.

package Polymorphism;
import java.util.Scanner;

// 부모클래스_OverWatch
interface OverWatch {
	// 전부다 추상메서드이니 interface로 선언한다.
	void name();
	void leftClick();
	void rightClick();
	void shiftButton();
	void eButton();
	void qButton();
}

// 자식클래스
// 메이
class Mei implements OverWatch {
	
	@Override
	void name() {
		System.out.println("이 름 : 메이");
		
	}
	
	@Override
	void leftClick() {
		System.out.println("왼쪽 버튼 : 냉각중");
		
	}
	
	@Override
	void rightClick() {
		System.out.println("오른쪽 버튼 : 고드름");
		
	}
	
	@Override
	void shiftButton() {
		System.out.println("Shift 버튼 : 급속 빙결");
	}
	
	@Override
	void eButton() {
		System.out.println("e 버튼 : 빙벽");
		
	}
	
	@Override
	public void qButton() {
		System.out.println("q 버튼 : 눈보라");
		
	}
}

class Gengi implements OverWatch {

	@Override
	void name() {
		System.out.println("이 름 : 겐지");

	}

	@Override
	void leftClick() {
		System.out.println("왼쪽 버튼 : 표창던지기");

	}

	@Override
	void rightClick() {
		System.out.println("오른쪽 버튼 : 표창 3개 던지기");

	}

	@Override
	void shiftButton() {
		System.out.println("Shift 버튼 : 돌진");

	}

	@Override
	void eButton() {
		System.out.println("e 버튼 : 칼로 막기");

	}

	@Override
	void qButton() {
		System.out.println("q 버튼 : 칼로 썰기(죽이기)");

	}

}

// 맥크리
class Mccree implements OverWatch {


	@Override
	void name() {
		System.out.println("이 름 : 맥크리");

	}

	@Override
	void leftClick() {
		System.out.println("왼쪽 버튼 : 피스키퍼");

	}

	@Override
	void rightClick() {
		System.out.println("오른쪽 버튼 : 모든 총알 발사");

	}

	@Override
	void shiftButton() {
		System.out.println("Shift 버튼 : 구르기");

	}

	@Override
	void eButton() {
		System.out.println("e 버튼 : 섬광탄");

	}

	@Override
	void qButton() {
		System.out.println("q 버튼 : 황야의 무법자");

	}

}


public class Ex02_Game {

	public static void main(String[] args) {
		
		Scanner sc = new Scanner(System.in);
		
		OverWatch watch = null;
		
		System.out.println("플레이할 캐릭터 선택(1.메이 / 2.겐지 / 3.맥크리)");
		
		int bunho = sc.nextInt();
		
		if(bunho == 1) {
			watch = new Mei();     //다형성
		} else if(bunho == 2) {
			watch = new Gengi();   //다형성
		} else if(bunho == 3) {
			watch = new Mccree();  //다형성
		}
		
		watch.name();
		watch.leftClick();
		watch.rightClick();
		watch.shiftButton();
		watch.eButton();
		watch.qButton();
		
		sc.close();

	}

}

재정의 된 메서드가 호출된다.

댓글