본문 바로가기
좋은 개발자가 되기위한 방법들/객체지향

객체지향 4대특성 (다형성) 쉽게정리

by chief_sac 2021. 9. 29.
반응형

 

 

이틀 동안 일을 하며 남는시간에 객체지향에서 말하는 다형성이란 무엇인가에대해 공부하며 정리해보았습니다.

 

참고자료

  • 오브젝트: 코드로이해하는 객체지향설계 (저자: 조영호),
  • 객체지향의 사실과 오해 (저자: 조영호)
  • TCPSchool.com( Java Part.43 다형성의개념)

 

상속과도 많은 연관이되니 상속에 대한것을 먼저 공부해본 이후에 하는 것이 좋을 것 같습니다.

먼저 다형성이라는 말 자체가 생소하여 다형성이라는 말을 먼저 해석해보자면

 

  • 사전적의미
다형성(Polymorphism)이라는 말은 그리스어에서 '많은' 을 뜻하는 poly와 '형태'를 의미하는 morph의 합성어로 많은 형태를 가질수 있는 능력을 의미합니다.
  • 컴퓨터과학에서 의미
서로 다른 유형의 객체가 동일한 메세지에 대해서 서로 다르게 반응하는 즉, 다형성은 여러타입을 대상으로 동작 할 수 있는 코드를 작성할 수 있는 방법이라고 합니다.

 

다향성의 분류


 

또한 다형성은 크게 유니버셜과 애드혹(임시)으로 나뉘어지는데 이 기준은 " 동일한 코드가 여러가지 타입에 대해서 사용되는것을 유니버셜 다향성이라 하고 실제로는 서로 다른 코드가 각각의 타입에대해 사용되는것을 애드혹 다향성이라고 부른다.

그 아래로는 매개변수포함, 오버로딩 강제 로 쪼개진다

  • 유니버셜 다형성은 매개변수와 포함이 있고 임시(애드혹)의 경우 오버로딩과 강제를 가지고있다.

  • 오버로딩 다형성
    • 일반적으로 클래스 안에서 동일한 이름의 메서드가 존재하는경우를 오버로딩 다형성이라고 지칭하고 이를 구분짓기위해 우리는 다른 파라미터를 받는다.

    Class MyName{
    // 내 성
    	public void printData(char firstName){
    		System.out.println("성 : " + age);
    	}
    // 내이름
    	public void printData(String name){
    		System.out.println("이름 : " + name);
    	}
    }​
    • 위와 같이 메서드 명이 동일하지만 파라미터 타입이 다르니 유사한 작업을 수행하는 메서드의 이름을 분리하여 우리가 머리속으로 기억해야하는 이름의 수를 극적으로 줄이는 방법이다.

 

  • 강제다형성
    • Corecion 즉 한글로 강제 자체를 생각해보면 우리가 무엇을 강제하는지만 이해하면 쉽게되는데 이것은 우리가 처음 Java를 배웠을때를 떠올려보면 이해가 가는 부분이 많다.

    String number1 = "3";
    int number2 = 3;
    
    System.out.println(number1 + number2);​
    • 우리가 위 코드를 실행하려고 한다면 Type오류가 나야하지만 "33"이 출력이된다 문자 3과 숫자3이 이항연산자를 통해 계산이 안되어야하는데 이렇게 계산이된다.
    • 즉 자바에서는 정수형과 문자열을 연산할때는 문자열로 강제변환하여 연결 연산을 하는것이다.
    • 이러한 부분이 객체지향의 다형성이라는 것의 분류되어있는 Coercion메커니즘인 것이다.

 

  • 매개변수 다형성
    • Java를 어느정도 배우면 알게되는 제네릭 프로그래밍과의 관련성이 높은 매개변수의 다향성은 우리가 어떠한 객체의 행위나 상태에대해 정의를 할때 명확하게 지정하지 못할때 자주 사용이되는데 이는 쉽게 볼 수 있지만 정확한 예시를 위해 Stack관리에대한 예시로 들면 좋을것 같다.
    Class Stack<T>{
    	public void work(T){
    		....
    	}
    	public T top(){...}
    }​

    • 어떠한 일을 하기위해 파라미터를 넘길때에 타입을 인지화하여서 값을 정하여 넣는 매커니즘으로 객체가 생성되는 시점에 타입을 결정함으로서 재사용성을 높이고 사용에있어 편리한 다형성을 제공해준다.

 

  • 포함 다형성
    • 포함다형성은 보내는 메세지가 동일해도 수신한 객체의 타입에 따라서 실제로 수행되는 행동이 달라지는 것을 의미하는데 이렇게 말했을때는 잘 안본것같지만

    • 실제로는 객체지향에서 말하는 다형성 하면 포함다형성을 말할정도로 중요하다.

    • 포함다형성은 서브타입 다형성이라고 부르기도한다.

    • 어떤 타입 T를 필요로하는 상황의 경우 타입 T를 가지는 객체 뿐만 아니라 서브타입(SubType)을 가지고있는 객체도 대신해서 사용할 수 있다.

    • 예를 들면 우리가 클래스를 상속관계로 연결하고 자식 클래스에서 부모 클래스의 메서드를 오버라이딩 한 후 클라이언트는 부모클래스만 참조한다면 쉽게 포함다형성을 구현할 수 있다.
    class T { ... }
    
    class Tcase1 extends T { ... }
    
    class Tcase2 extends T { ... }
    
    Class Main(){
    	public static void main(String[] args) {
    		T ex1 = new T();
    		Tcase1 ex2 = new Tcase1();
    		Tcase2 ex3 = new Tcase2();
    		
    		func(ex1);  //오류안남
    		func(ex2);  //오류안남
    		func(ex3);  //오류안남
    	}
    
    	public func(T param){
    		...
    	}
    }​

    • 분명 다른 클래스에서 객체를 생성한것같지만 객체가 메세지를 수신할때 메세지를 처리할 적절한 메서드를 상속계층에서도 찾아서 실행하기때문이다.

    • 결국 상속이 필요한 진짜목적은 코드 재사용이아니라 다형성을 위한 서브타입계층을 구축하기위함이라고 표현한다.

 

 

위 내용들이 조금은 복잡하다 싶을때 나는 책에서 나온 비유를 통해 아! 소리가 나왔다.

만약 나와 비슷한 경우 보면 좋을것같아 내마음대로 변경하여 인용하자면

어떠한 왕이 신하들에게 각각 같은 어명이 담긴 두루마리를 "전달하라" 라는 명하였을때
신하들은 각자 "말을타고간다", "걸어간다" , "가마를 타고간다" 등
다양한 방법이 있을것인데왕의 입장에서는 결과가 동일하다.

이것이 의미하는것은 즉,
이들은 결국 모두 전달하는 명을 듣고있는것이라는 것이다.

 

 

위와 비슷한 비유를 들었는데 결국 다형성은 동일한 역할을 수행할 수 있는 객체들 사이의 대체 가능성을 의미하여 설계와 프로그램을 유연하고 재사용가능하게 만드는 행위이다.

반응형