[OOP] 폴리모피즘 (Polymorphism, 다형성)

calm0_0·2023년 9월 6일
0

OOP

목록 보기
1/6

폴리모피즘(Polymorphism) 이란?


폴리모피즘(다형성)이란 어떤 객체의 속성이나 기능이 상황에 따라 여러 가지 형태를 가질 수 있는 성질을 말한다.

이는 같은 그룹에 속하는 클래스들의 동일한 메서드 호출할 때, 자식 클래스들이 저마다 다른 로직을 수행하고 리턴하는 것이다.


폴리모피즘의 구현 예시


다음과 같이 비행기 클래스 그룹이 있다. 여기에는 부모 클래스(DefaultAirplane)와 자식 클래스(PropellerAirplane, JetAirplane, StealthAirplane)들이 있고 다음과 같이 정의하였다.

// 부모 클래스
public class DefaultAirplane {
	public void airplaneFeature() {
    	System.out.println("이 비행기는 기본 비행기");
    }
}
public class PropellerAirplane extends DefaultAirplane {
	@Override
    public void airplaneFeature() {
    	System.out.println("이 비행기는 프로펠러 엔진 기반");
    }
}

public class JetAirplane extends DefaultAirplane {
	@Override
    public void airplaneFeature() {
    	System.out.println("이 비행기는 제트 엔진 기반");
    }
}

public class StealthAirplane extends DefaultAirplane {
	@Override
    public void airplaneFeature() {
    	System.out.println("이 비행기는 스텔스 기반");
    }
}

이 클래스 그룹은 비행기의 특징을 설명해주는 airplaneFeature() 메서드를 가지고 있다. airplaneFeature() 메서드는 각 비행기 클래스마다 구현 방식이 다르다.

public class Pilot {
	DefaultAirplane defaultAirplane1;
	
	// 파일럿 생성자에서 비행기 객체를 받아 저장한다.
	public Pilot(DefaultAirplane defaultAirplaneReceived) {
		defaultAirplane1 = defaultAirplaneReceived;
	}
    
    // 메소드에서도 비행기 객체를 교체할수 있게 만들었다.
	public void setAirplane(DefaultAirplane defaultAirplaneReceived) {
		defaultAirplane1 = defaultAirplaneReceived;
	}
	
	// 비행기 타기
	public void intoAirplane() {
		defaultAirplane1.airplaneFeature();
	}
}

Pilot 클래스는 비행기 클래스 그룹의 기능을 제공 받아 사용하는 클라이언트 클래스이다.

Pilot defaultPilot = new Pilot(new DefaultAirplane());
defaultPilot.intoAirplane();
		
Pilot propellerPilot = new Pilot(new PropellerAirplane());
propellerPilot.intoAirplane();
		
Pilot jetPilot = new Pilot(new JetAirplane());
jetPilot.intoAirplane();
		
Pilot stealthPilot = new Pilot(new StealthAirplane());
stealthPilot.intoAirplane();

// 이 비행기는 기본 비행기
// 이 비행기는 프로펠러 엔진 기반
// 이 비행기는 제트 엔진 기반
// 이 비행기는 스텔스 기반

이를 실행 클래스에서 실행한 결과이다. 클라이언트 클래스(Pilot)에서는 사용하려는 클래스 그룹의 부모 클래스에만 의존하고 자식 클래스를 인자로 넘겨 받아 저장하고 있다.

실행 클래스의 다음 코드를 분석해보자.

Pilot propellerPilot = new Pilot(new PropellerAirplane());
propellerPilot.intoAirplane();

Pilot 객체를 생성하면서 PropellerAirplane 객체를 생성하여 Pilot 클래스 생성자의 인자로 넘겼다.

Pilot 클래스에서는 생성자에서 DefaultAirplane 인터페이스의 PropellerAirplane 로직으로 생성된 defaultAirplaneReceived 객체를 인자로 받아 defaultAirplane1 전역 변수에 저장한다.

intoAirplane() 메서드에서는 DefaultAirplane 인터페이스의 PropellerAirplane 로직으로 저장된 defaultAirplane1 객체의 airplaneFeature 메서드를 실행한다.


폴리모피즘의 장점


폴리모피즘으로 구성했을 때 장점

폴리모피즘으로 구성할 때의 장점으로는 다음과 같은 것들이 있다.

  1. 관계의 의존성이 낮아진다.

    • 예제에서 Pilot 클래스는 프로펠러 비행기를 탈 때도, 제트 비행기를 탈 때도, 스텔스 비행기를 탈 때도 오직 DefaultAirplane 에만 의존한다. 그래서 관계의 의존성이 확 낮아진다.
  2. 클라이언트 클래스(Pilot)의 변경 없이, 기능의 수정과 확장이 무제한으로 가능하다.

Pilot pilot = new Pilot(new DefaultAirplane());
pilot.intoAirplane();
		
pilot.setAirplane(new PropellerAirplane());
pilot.intoAirplane();

pilot.setAirplane(new StealthAirplane());
pilot.intoAirplane();
		
pilot.setAirplane(new JetAirplane());
pilot.intoAirplane();		

// 이 비행기는 기본 비행기
// 이 비행기는 프로펠러 엔진 기반
// 이 비행기는 제트 엔진 기반
// 이 비행기는 스텔스 기반

다음과 같이 Pilot 클래스의 변경 없이도 프로그램 실행 중에도 자유롭게 비행기 객체를 교체하고 있다.

폴리모피즘으로 구성하지 않았을 때 문제점

다음은 위 예제를 폴리모피즘으로 구성하지 않았을 때의 코드 예시이다.

public class Pilot {
	String code = "";
	
	public Pilot(String codeReceived) {
		this.code = codeReceived;
	}
	
	// 비행기 타기
	public void intoAirplane() {
		if(code.equals("프로펠러 비행기")) {
			PropellerAirplane pAirplane = new PropellerAirplane();
			pAirplane.airplaneFeature();
		} else if(code.equals("제트 비행기")) {
			JetAirplane jAirplane = new JetAirplane();
			jAirplane.airplaneFeature();
		} else if(code.equals("스텔스 비행기")) {
			StealthAirplane pAirplane = new StealthAirplane();
			pAirplane.airplaneFeature();
		}  else if(code.equals("점보 비행기")) {
			// 관련 로직 
		}  else if(code.equals("스페이스 셔틀")) {
			// 관련 로직 
		}      
	}
}	
public class LaunchMain {
	public static void main(String[] args) {
		Pilot defaultPilot = new Pilot("프로펠러 비행기");
		defaultPilot.intoAirplane();
		
		defaultPilot = new Pilot("제트 비행기");
		defaultPilot.intoAirplane();
		
		defaultPilot = new Pilot("스텔스 비행기");
		defaultPilot.intoAirplane();
	}
}

Pilot 클래스는 코드값을 받고, 이에 따라 if문으로 분기하여 조건에 맞는 비행기 객체를 직접 의존하여 실행한다.

이에 따라 발생하는 단점은 다음과 같다.

  1. 의존성이 심해진다.
  2. 비행기 기능이 변경 또는 확장될 경우 기존 코드도 따라서 수정되어야 한다. (Pilot 클래스에서는 비행기의 종류가 추가될 때마다 if 문을 추가하고 있다.)

폴리모피즘을 쓰기 위해 지켜야할 원칙 3가지


폴리모피즘을 효과적으로 활용하기 위해서는 다음의 3가지 원칙을 지켜야 한다.

  1. '기능을 제공할' 비슷한 종류의 클래스들을 모아 클래스 그룹으로 조직화한다.
  2. 기능을 제공할 클래스 그룹의 인터페이스를 통일한다.
  3. 클라이언트 클래스에서는 쓰고 싶은 클래스 그룹의 부모 클래스만 의존하고 자식 클래스를 인자로 넘겨받아 저장한다.


Reference
한 번 읽으면 두 번 깨닫는 객체지향 프로그래밍

profile
공부한 내용들을 정리하는 블로그

0개의 댓글