본문 바로가기
Back/JAVA

상속 - 다형성(polymorphism)

by 시월해 2021. 3. 12.

 * 다형성(polymorphism)?

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

 

 * instanceof 연산자

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

 


기본예제)

public interface Animal {
	
	void sound(); //추상메서드
	
}
public class Cat implements Animal{

	@Override
	public void sound() {
		System.out.println("냐옹냐옹");
		
	}
}
public class Dog implements Animal{
	
	@Override
	public void sound() {
		System.out.println("멍멍멍~~~");
		
	}
	
	void output() {
		System.out.println("Dog Class method");
	}

}
public class Tiger implements Animal{

	@Override
	public void sound() {
		System.out.println("어흐응어흥어흥");
		
	}
}
public class Ex01_Animal {

	public static void main(String[] args) {
		
		Dog dog = new Dog();
		Cat cat = new Cat();
		Tiger tiger = new Tiger();
		
		dog.sound();
		cat.sound();
		tiger.sound();
		System.out.println();
		
		// 다형성을 이용하여 객체를 생성.
		Animal animal1 = new Dog();
		animal1.sound();
		// 다형성을 이용하여 부모의 참조변수로 자식의 객체를 생성했을 때
		// 부모에는 없는 자식의 멤버는 호출할 수 없다.
		// animal1.output()
		
		Animal animal2 = new Cat();
		animal2.sound();
		
		Animal animal3 = new Tiger();
		animal3.sound();
		
		// 자식에는 있는 멤버가 부모에는 없을 수 있기 때문에 자식이 부모의 객체로는 생성 불가.
		//Dog animal10 = new Animal();
		

	}

}


예제1) 인터페이스 상속 받은 클래스를 다형성을 사용하여 객체 생성

public interface OverWatch {

	// 전부다 추상메서드이니 interface로 선언한다.
	void name();
	void leftClick();
	void rightClick();
	void shiftButton();
	void eButton();
	void qButton();
}
public class Mei implements OverWatch {
	
	@Override
	public void name() {
		System.out.println("이 름 : 메이");
		
	}
	
	@Override
	public void leftClick() {
		System.out.println("왼쪽 버튼 : 냉각중");
		
	}
	
	@Override
	public void rightClick() {
		System.out.println("오른쪽 버튼 : 고드름");
		
	}
	
	@Override
	public void shiftButton() {
		System.out.println("Shift 버튼 : 급속 빙결");
	}
	
	@Override
	public void eButton() {
		System.out.println("e 버튼 : 빙벽");
		
	}
	
	@Override
	public void qButton() {
		System.out.println("q 버튼 : 눈보라");
		
	}
}
public class Gengi implements OverWatch {

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

	}

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

	}

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

	}

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

	}

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

	}

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

	}

}
public class Mccree implements OverWatch {


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

	}

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

	}

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

	}

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

	}

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

	}

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

	}

}
import java.util.Scanner;

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();

	}

}

 


예제1-2) 예제1에서 만든 게임 관련 메소드들의 instanceof 연산자 활용

public class Ex04_Game2 {

	public static void main(String[] args) {
		
		Gengi gengi = new Gengi();
		
		if(gengi instanceof Gengi) {
			System.out.println("Gengi 클래스 타입입니다.");
		}
		
		if(gengi instanceof OverWatch) {
			// 상속받았기 때문에 같은 타입 취급한다.
			System.out.println("조상 클래스 타입입니다.");
		}

	}

}

 


예제2) 다형성 예시

class A {}

class B extends A {}

class C extends A {}

class D extends B {}

class E extends C {}

public class Ex03_Main {

	public static void main(String[] args) {
		B b = new B();
		C c = new C();
		D d = new D();
		E e = new E();
		
		A a1 = b;
		A a2 = c;
		A a3 = d;
		A a4 = e;
		
		B b1 = d;
		C c1 = e;
		
		//e는 C를 상속 받았고, d는 b를 상속 받았기 때문에 다형성으로 객체 생성할 수 없다.
		//B b2 = e;
		//C c2 = d;
		
		// instanceof : 두 개의 객체가 같은 지 물어보는 연산자
		if(d instanceof B) {
			System.out.println("true");
		}

	}

}