검수요청.png검수요청.png

다형성

위키원
이동: 둘러보기, 검색

다형성(多形性, polymorphism)이란 프로그래밍 언어의 자료형 체계의 성질을 나타내는 것으로, 프로그램 언어의 각 요소들(상수, 변수, , 객체, 함수, 메소드 등) 다양한 자료형(type)에 속하는 성질을 말한다.[1] 영어 발음대로 폴리모피즘(polymorphism)이라고 하기도 한다. 다형성으로 인해 하나의 함수상속을 통해 기능을 확장시키고 더 변경하는 것이 가능하다. 자바에서 다형성을 부모 클래스 타입의 참조변수로 자식 클래스 타입의 인스턴스를 참조할 수 있도록 하여 구현한다. 다형성은 상속, 추상화와 더불어 객체 지향 프로그래밍을 구성하는 중요한 특징 중 하나이다.[2] 다형성의 반대말은 단형성(monomorphism)으로, 프로그램 언어의 각 요소가 한 가지 형태만 가지는 성질을 가리킨다.

개요

여러 개의 형태를 갖는다는 의미로, 객체 지향 프로그래밍의 3대 특징 중 하나이다. 상속을 이용한 기술로, 자식 객체를 부모 클래스 타입의 변수로 다룰 수 있다. 메소드 호출 시 다형성을 이용하여 부모 타입의 매개변수를 사용하면서 자식 타입의 객체를 받을 수 있다.[3] 다형성이란 같은 자료형에 여러 가지 객체를 대입하여 다양한 결과를 얻어내는 성질을 의미한다.[4]

구성 요소

서브타입 다형성

서브타입 다형성(Subtype Polymorphism / Inclusion Polymorphism / Subtyping) : 서브타입 다형성은 객체 지향에서 흔히 얘기하는 다형성을 이야기한다. 서브타입 다형성의 핵심은 바로 대치 가능성(Substitutability)라고 하는 것이다. 어떤 타입의 클래스를 요구하는 상황에서 클래스를 가지는 객체뿐만 아니라 그것의 서브타입(subtype)을 가지는 객체도 대신 사용할 수 있다는 것이다.[5] 기초 클래스 또는 어떠한 인터페이스를 구현하는 상위 클래스를 생성하고, 해당 클래스를 상속받는 다수의 하위 클래스들을 만들어 상위 클래스의 포인터나 참조 변수 등이 하위 클래스의 객체를 참조하게 하는 것이다. 이때 각각의 하위 클래스는 상위 클래스의 메소드 위에 자신의 메소드를 덮어쓰는 메소드 오버라이딩(Method overriding)을 수행하며, 상위 클래스의 참조 변수가 어떤 하위 클래스의 객체를 참조하느냐에 따라 호출되는 메소드가 달라진다. Java, C++, C#, Python, Ruby 등의 객체 지향 언어들은 기본적으로 지원하는 개념이다.[6]

매개변수 다형성

매개변수 다형성(Parametric Polymorphism) : 어떤 소프트웨어 시스템을 개발하든지 간에 자료구조는 필수적으로 사용된다. 타입을 매개변수로 받아 새로운 타입을 되돌려주는 기능이다. 타입 매개변수를 정의한 클래스 혹은 메소드는 사용할 때 매개변수에 타입을 지정하게 되며, 컴파일 시 지정한 타입에 따라 해석된다.[6] 스택, , 트리, 테이블 등이 바로 그런 것들인데. 파라메트릭 다향성은 타입이 다르기 때문에 모든 코드를 다시 작성해야 하는 문제를 해결해 주기 위해서 존재한다고 봐도 된다. 그렇기에 실용적으로 매우 편리하다는 장점을 가진다.[5] 매개 변수 다형성은 단일 다형성 기능이 적용되는 인수의 유형에 따라 다수의 구별되고 잠재적으로 이질적인 구현이 가능하기 때문에 임시 다형성과 대조될 수 있다.[7]

상속 다형성

부모클래스를 상속 받은 자식클래스들을 부모클래스 타입의 매개변수로 받아올 수 있는 특성이 있다.

템플릿

템플릿(Template) : C++에서 사용하는 개념으로, 타입 매개변수를 입력한 타입으로 치환한 코드를 생성하는 방식이다. 타입뿐 아니라 변수도 입력할 수 있으며, 객체 내부에서 연산이나 함수 호출을 할 수 있지만, 해당 연산이나 함수가 정의되지 않은 타입을 매개변수로 넣으면 컴파일 에러가 발생하며 컴파일이 느려지고 파일이 커진다.

제네릭

제네릭(Generic) : Java와 C# 등에 도입된 개념으로, 지정한 타입 매개변수에 해당하는 타입만을 사용하겠다고 약속하는 방식이다. 타입 매개변수가 특정 객체를 상속할 경우 상속하는 객체의 함수는 호출할 수 있지만 그렇지 않을 경우 타입 매개변수로 지정된 객체의 멤버에는 접근할 수 없다.

임시 다형성

임시 다형성(Ad hoc Polymorphism) : 다성체 기능이 적용되는 인수의 유형에 따라 다수의 구별이 가능하고 잠재적으로 이질적인 구현이 가능하기 때문에 다중 형태 기능이 다른 유형의 인수에 적용 가능한 다형성의 일종이라고 볼 수 있다. 객체 지향적 또는 절차적 개념에 적용될 경우에는 기능 과부하, 운영자 과부하라고 불린다. 단순히 이런 유형의 다형성이 형식 시스템의 근본적인 특징이 아니라는 사실을 알 수 있고 이는 특정 유형에 대한 언급이 없이 다형성이라는 기능을 사용하고 투명한 방법으로 모든 유형에 단일 추상적 구현을 적용할 수 있는 매개변수 다형성과 다르다고 볼 수 있다.[8] 애드혹 다형성에는 오버로딩, 코어션이 모여있다고 볼 수 있다.[5] 임시 다형성은 파견 메커니즘으로 호출되는 정확한 기능을 지정할 필요 없이 하나의 명명된 기능을 통해 이동하는 제어가 다양한 다른 기능으로 파견된다. 과부하는 다른 유형의 기능을 동일한 이름으로 정의할 수 있게 해 주며, 컴파일러나 번역기는 자동으로 올바른 기능이 호출되도록 보장한다.[8]

함수 오버로딩

함수 오버로딩(Function overloading) : C++과 C#, Java에서는 함수 오버로딩을 통해 동일한 이름의 함수를 매개변수에 따라 다른 기능으로 동작하도록 할 수 있다. 함수 오버로딩을 너무 많이 사용하면 전체적인 코드의 유지 보수가 어려워지므로, 템플릿 또는 제네릭으로 대체하는 것이 일반적이다.[6]

연산자 오버로딩

연산자 오버로딩(Operator overloading) : C++, C# 등에서는 연산자를 오버로딩해서 기본 연산자가 해당 클래스에 맞는 역할을 수행하게 하는 것이 가능하다. Java에서는 연산자의 오버로딩이 불가능하다. Perl 6나 Smalltalk, F#, Kotlin 등 연산자의 신규 정의가 가능한 언어도 있다.[6]

강제 다형성

강제 다형성(Coercion Polymorphism) : 형식 인수가 기능 인수의 필요한 유형에서 다른 유형의 강제력을 허용하는 함수다. 연산자는 실제 숫자만 허용할 수 있지만 정수 유형은 피연산자에서 연산자가 호출되기 전에 강제적으로 실제 형식이 된다. 그렇지 않을 경우에는 유형 오류가 발생할 수 있다. [9]

묵시적 형 변환

묵시적 형 변환(Implicit type coercion) : 암시적 형 변환이라고도 불리며 컴파일러가 자동으로 변환하는 형 변환이다. [10]'double a = 30;'이라는 식이 실행되면 int형 값 30은 double로 묵시적 형 변환이 이루어진다. double은 int보다 크기가 큰 자료형이므로, 이러한 형 변환을 자료형 승급(Type promotion)이라고 한다. C++의 변환 생성자에 의한 형 변환도 묵시적 변환에 속하며, 이를 막으려면 생성자 앞에 explicit 키워드를 추가해야 한다.[6]

명시적 형 변환

명시적 형 변환(Explicit type coercion) : 'double a = (double)30;'이라는 식은 위와 동일한 결과를 내지만, (double)을 통해 int형 값 30이 double형으로 변환됨을 명시적으로 표현하였다.[6]

특징

  • 부모 클래스 타입의 참조 변수로 자식 클래스의 인스턴스 참조 가능. 부모 클래스 타입의 참조 변수로 자식 클래스에 있는 멤버들에 접근 가능하다. (부모 클래스에서 상속받은 멤버만 접근 가능. 자식 클래스에서 만들어진 멤버들은 접근 불가.)[11]
  • 자식 타입의 참조 변수로 부모 타입의 인스턴스로 참조 불가하다.[11]
  • 반드시 상속관계가 이뤄져야 한다.[11]
  • 상속과 인터페이스를 통해 이루어진다.
  • 인터페이스가 상속보다 다형성에 더욱 유연함을 제공한다.

활용

단형성 체계를 가진 프로그램 언어에서는 함수는 각각 한 가지 의미로 식별되는 이름과 결합되어 있어 다른 동작을 구현하기 위해서는 다른 이름을 써야 한다. 예를 들어 어떤 값을 문자열 형식으로 변환하는 단순한 경우를 생각하며, 단형성 형태 체계를 가지지 못한 언어에서는, 개별 함수일 것이다.[1]

//숫자를 문자열로 바꾸는 경우
string = StringFromNumber(number);
//날짜를 문자열로 바꾸는 경우
string = StringFromDate(date);

한편 다형성 체계를 가진 언어에서는, StringValue와 같은 범용 메소드 이름을 정의하여 형태에 따라 각각 적절한 변환 방식을 정의해둠으로써 객체의 종류와 상관없는 추상도가 높은 변환 형식을 구현할 수 있다.[1]

//숫자를 문자열로 바꾸는 경우
string = number.StringValue();
//날짜를 문자열로 바꾸는 경우
string = date.StringValue();

물론 StringValue 메소드의 정의는 형태별로 따로 수행되어야 하기 때문에 전체적으로 코드의 분량이 감소하는 것은 아니다.(다만 상속에 의한 재사용 가능). 추가로 '올바른 동작'에 관한 것은 객체의 설계에 따라 달라질 수 있으므로, 다형성을 잘 다루려면 체계 전체를 파악하는 뛰어난 설계 능력이 요구된다고 볼 수 있다.[1]

각주

  1. 1.0 1.1 1.2 1.3 다형성(컴퓨터 과학)〉, 《위키백과》, 2020-04-24
  2. 다형성의 개념〉, 《코딩의 시작, TCP School》
  3. 자바 이론# 다형성~네트워크〉, 《codepark_kr.log》2020-05-29
  4. (JAVA/자바) 다형성(polymorphism)의 개념/의미/예제〉, 《JOKER's ROOM》2017-04-10
  5. 5.0 5.1 5.2 객체지향 프로그래밍5-다형성〉, 《IT 공부하기》, 2009-08-04
  6. 6.0 6.1 6.2 6.3 6.4 6.5 객체 지향 프로그래밍〉, 《나무위키》
  7. Parametric polymorphism〉, 《WIKIPEDIA》, 2020-06-05
  8. 8.0 8.1 Ad hoc polymorphism〉, 《WIKIPEDIA》, 2020-07-07
  9. Polymorphism in programming languages〉, 《Theory of Objects》
  10. 형 변환〉, 《위키백과2》, 2020-07-08
  11. 11.0 11.1 11.2 다형성〉,《윤연식》, 2008-0-13

참고자료

같이 보기


  검수요청.png검수요청.png 이 다형성 문서는 프로그래밍에 관한 글로서 검토가 필요합니다. 위키 문서는 누구든지 자유롭게 편집할 수 있습니다. [편집]을 눌러 문서 내용을 검토·수정해 주세요.