티스토리 뷰

JAVA

TIL(9) 다형성 - 코드적 접근

나죽나강 2021. 5. 27. 03:56

# 목표

1. 객체지향에서 다형성이 어떻게 사용이 되는지 이해하기!

2. 다형성은 객체나 인터페이스 또는 추상과 같이 철학적인 느낌으로 이해하는 것은 혼란을 느낄수 있다고 생각합니다. 그래서 코드 상에서 구체적으로 어떤 모습으로 드러나는지에 집중하고자 하였습니다. 

 

# 다형성이란?

> 다형성은 여러 객체에게 동일한 명령을 내렸을 때 서로 다르게 반응하는 현상을 의미합니다. 

> 자바에서는 다형성을 이용하여 객체를 사용할 때 사용하는 변수 형태를 바꾸어 여러 타입의 객체를 참조할 수 있습니다. 결과적으로 이러한 다형성의 개념을 적절하게 이용할 때 프로그램의 소스 코드를 유연하게 구성할 수 있습니다.

 

/** 우테코 블로그 참조(코드) */

https://woowacourse.github.io/javable/post/2020-10-27-polymorphism/

// 도형
public abstract class Figure {
    protected int dot;
    protected int area;

    public Figure(final int dot, final int area) {
        this.dot = dot;
        this.area = area;
    }

    public abstract void display();
}

// 삼각형, 사각형, 오각형...
public class Triangle extends Figure {
    public Triangle(final int dot, final int area) {
        super(dot, area);
    }

    @Override
    public void display() {
        System.out.printf("넓이가 %d인 삼각형입니다.", area);
    }
}

// main메소드
public static void main(String[] args) {
    Figure figure = new Triangle(3, 10); // 도형 객체 추가 또는 변경 시 이 부분만 수정
	//Figure figure = new Triangle(4, 20);
    
    for (int i = 0; i < figure.getDot(); i++) {
        figure.display();
    }
}

 

# 다형성을 이용하지 못한다면?!

> 삼각형을 사각형으로 바꾸기 위해 많은 if-else문을 사용해야 한다.

public static void main1(String[] args) {
    int dot = SCANNER.nextInt();

    if (dot == 3) {
        Triangle triangle = new Triangle(3, 10);
        for (int i = 0; i < triangle.getDot(); i++) {
            triangle.display();
        }
    } else if(dot == 4) {
        Rectangle rectangle = new Rectangle(4, 20);
        for (int i = 0; i < rectangle.getDot(); i++) {
            rectangle.display();
        }
    }
	  ....

}

 

# 메소드와 다형성

https://opentutorials.org/module/516/6127

많은 책에서 오버라이딩과 오버로딩을 다형성의 예시로 들고 있다. 하지만! 오버라이딩과 오버로딩은 다형성을 대변하기에 많이 부족하다고 생각하기 때문에 다형성을 사용하는 예시를 메소드, 클래스, 인터페이스등을 사용해서 이해하는 것을 추천! 

+ 상속과 구현(인터페이스)의 관점에서도 고민해 볼것!!

 

# 클래스와 다형성

https://www.youtube.com/watch?v=TnvfaFNuF9U

개인적으로 정말 설명을 잘해주는 유튜브 영상이라고 생각합니다. C#으로 설명하지만 보는것을 추천!!

 

// 부모클래스 (유닛)
public class Unit {
	public String Attack() {
		return "공격(어택땅!)";
	}
}
//마린
public class Marine extends Unit {

	@Override
	public String Attack() {
		// TODO Auto-generated method stub
		return "탕탕탕";
	}
	
	public String SteamPack() {
		return "스팀 팩!";
	}
	
}
//탱크
public class Tank extends Unit{

	@Override
	public String Attack() {
		// TODO Auto-generated method stub
		return "통통통";
	}
	
	public String SizMode() {
		return "변신!";
	}
	
}
//히드라
public class Hydra extends Unit{

	@Override
	public String Attack() {
		// TODO Auto-generated method stub
		return "퉤퉤퉤";
	}
	
	public String Hide() {
		return "땅에 숨기!";
	}
	
}
// 스타 프로그램
public class StarCraft {
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		Marine marin_m = new Marine();
		Unit marin_u = new Marine();
		System.out.println(marin_m.Attack());
		System.out.println(marin_u.Attack());
		//탕탕탕
		//탕탕탕
		
		ArrayList<Unit> list = new ArrayList<Unit>();
		
		Marine marin = new Marine();
		Tank tank = new Tank();
		Hydra hydra = new Hydra();
		
		list.add(marin);
		list.add(tank);
		list.add(hydra);
		
		for(int i=0 ; i < list.size(); i++) {
			System.out.println(list.get(i).Attack());
		}
		//탕탕탕
		//통통통
		//퉤퉤퉤
		
	
	}
	
}

 

> Marine marin_m = new Marine();

> System.out.println(marin_m.Attack());

> Attack()과 SteamPack() 두 메소드를 모두 사용할 수 있다.

 

> Unit marin_u = new Marine();

> System.out.println(marin_u.Attack());

> Attack()만 사용할 수 있다

> 실행결과 역시 "탕탕탕(마린)"이 출력된다.

 

 

> 객체를 사용함으로써 다형성을 추구할수 있다고 생각한다.

> 또한 객체지향의 OCP를 추구함으로써 변화에 닫혀있고 확장에는 열려있는 코드를 구현할수 있다고 생각한다.

 

 

 

# 인터페이스와 다형성

/** 생활코딩 참조(코드) */

https://opentutorials.org/module/516/6127

interface Interface_A{
    public String A();
}
interface Interface_B{
    public String B();
}
class Interface_All implements Interface_A, Interface_B{
    public String A(){
        return "A";
    }
    public String B(){
        return "B";
    }
}
public class PolymorphismDemo3 {
    public static void main(String[] args) {
        Interface_All InterALL = new Interface_All();
        InterALL.A();
        InterALL.B();
        
        Interface_A InterA = new Interface_All();
        InterA.A();
        // InterA.B(); Error
        
        
        Interface_B InterB = new Interface_All();
        InterB.B();
        // InterB.A(); Error
    }
}

인터페이스의 매우 중요한 특징 중의 하나를 보여준다. 인스턴스 InterA의 데이터 타입을 Inteface_A로 한다는 것은 인스턴스를 외부에서 제어할 수 있는 조작 장치를 인스턴스 Inteface_A의 맴버로 제한한다는 의미가 된다. 인스턴스 Inteface_AInteface_B로 인해서 하나의 클래스가 다양한 형태를 띄게 되는 것이다.

 

 

결론

/** 우테코 블로그 인용*/

필자는 개인적으로 다형성이 객체 지향 패러다임의 주요 특성 중 가장 핵심이라고 생각한다. 변화에 유연한 소프트웨어를 만들기 위해서 객체 지향 패러다임을 사용하는 것이라면, 그러한 목적 달성에 중추적인 역할을 “다형성”이 해내기 때문이다.

우리는 객체 지향으로 설계를 잘하기 위한 원칙인 SOLID원칙을 알고 있다. SOLID 중에서도 가장 어려운 OCP(Open-Closed Principle)와 DIP(Dependency Inversion Principle)는 다형성을 기본으로 하고 있다. 물론 다형성을 사용하기 위해서는 추상화, 상속 개념이 필요하긴 하지만 본질적인 목적을 본다면 결국은 다형성을 잘 활용하는 것이 코드의 중복을 줄이면서 변경과 확장에 유연한 객체 지향적인 코드를 작성하는데 유용하다는 것을 알 수 있을 것이다.

정리하면 다형성은 하나의 타입에 여러 객체를 대입할 수 있는 성질이고, 이것을 구현하기 위해서는 여러 객체들 중 공통 특성으로 타입을 추상화하고 그것을 상속(인터페이스라면 구현)해야한다. 이 특성들을 유기적으로 잘 활용했을 때, 비로소 객체 지향에 가까운 코드를 작성할 수 있을 것이라 생각한다.

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2026/04   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30
글 보관함