맨위로가기

다형성 (컴퓨터 과학)

"오늘의AI위키"는 AI 기술로 일관성 있고 체계적인 최신 지식을 제공하는 혁신 플랫폼입니다.
"오늘의AI위키"의 AI를 통해 더욱 풍부하고 폭넓은 지식 경험을 누리세요.

1. 개요

다형성(Polymorphism)은 컴퓨터 과학에서 서로 다른 유형의 객체가 동일한 인터페이스를 공유하여 동일한 방식으로 처리될 수 있는 능력을 의미한다. 1960년대부터 연구가 시작되었으며, 크리스토퍼 스트레이치가 임시 다형성과 매개변수 다형성 개념을 처음 제안했다. 다형성은 임시 다형성, 매개변수 다형성, 서브타입 다형성, 로 다형성, 폴리타이피즘, 랭크 다형성 등 다양한 종류로 나뉘며, 구현 시점에 따라 정적 다형성과 동적 다형성으로 구분된다. 다형성의 반대 개념은 단태성이다.

더 읽어볼만한 페이지

  • 다형성 (컴퓨터 과학) - 공변성과 반공변성 (컴퓨터 과학)
    자료형 체계에서 타입 생성자가 타입 매개변수의 하위 타입 관계를 정의하는 방식인 공변성과 반공변성은 상속 관계 유지, 반대 적용, 관계 없음으로 나뉘며 타입 안전성과 코드 유연성에 기여하며 범주론에서 유래되었습니다.
  • 제네릭 프로그래밍 - 표준 템플릿 라이브러리
    표준 템플릿 라이브러리(STL)는 알렉산더 스테파노프의 주도로 탄생한 C++ 라이브러리로서, 제네릭 프로그래밍을 지원하기 위해 컨테이너, 반복자, 알고리즘, 함수 객체 등의 핵심 구성 요소로 이루어져 있으며, HP에서 무료로 공개한 구현을 기반으로 다양한 구현체가 존재한다.
  • 제네릭 프로그래밍 - Boost (C++ 라이브러리)
    Boost는 C++ 표준화에 영향을 준 라이브러리 모음으로, 다양한 기능과 자료 구조를 제공하며 템플릿 메타 프로그래밍과 제네릭 프로그래밍 기법을 활용하여 C++ 기술 발전에 기여한다.
  • 프로그래밍 언어 개념 - 참조
    참조는 프로그래밍에서 메모리 주소나 다른 데이터를 가리키는 값으로, 데이터의 효율적인 전달과 공유를 위해 사용되며, 포인터, 파일 핸들, URL 등이 그 예시이다.
  • 프로그래밍 언어 개념 - 자료형
    자료형은 프로그래밍 언어에서 데이터를 분류하고 관리하는 추상적인 분류 체계로, 값의 표현, 해석 및 구조에 제약 조건을 가하여 프로그램의 정확성을 검증하며, 단순형/복합형, 언어 정의형/사용자 정의형 등으로 분류되고 문자형, 수치형, 부울형 등 다양한 종류가 있다.
다형성 (컴퓨터 과학)
개요
정의다양한 타입에 대해 하나의 인터페이스 또는 심볼을 사용하는 것
관련 개념Ad hoc 다형성
매개변수 다형성
서브타이핑
Ad hoc 다형성
종류함수 오버로딩
연산자 오버로딩
매개변수 다형성
종류제네릭 함수
제네릭 프로그래밍
서브타이핑
종류가상 함수
단일 및 동적 디스패치
이중 디스패치
다중 디스패치
프레디케이트 디스패치

2. 역사

다형성 타입 시스템에 대한 관심은 1960년대부터 시작되었고, 1990년대에 들어 크게 발전했으며, 실질적인 구현은 1990년대 말에 나타나기 시작했다.[5] 크리스토퍼 스트레이치는 1967년 논문 ''프로그래밍 언어의 기본 개념''에서 ''임시 다형성''과 ''매개변수 다형성''을 다형성의 "두 가지 주요 클래스"로 설명했다.[5] 임시 다형성은 ALGOL 68에서 구현되었고, 매개변수 다형성은 ML의 타입 시스템의 핵심 기능이었다.

1985년, 피터 웨그너와 루카 카르델리는 상속 및 하위 유형을 모델링하기 위해 ''포함 다형성''이라는 용어를 도입했으며,[1] 이를 구현한 최초의 프로그래밍 언어로 시뮬라를 언급했다.[1]

1989년, 미첼 완드는 객체 지향의 동적 타이핑을 설명하기 위해 Row polymorphism|로 다형성영어 개념을 제안했지만, 인지도는 낮다. 같은 해, 알렉산더 스테파노프 등은 매개변수 다형성을 기반으로 하는 제네릭 프로그래밍(폴리타이피즘)을 제안했다.[19]

1980년대 Ada는 제네릭스에 형식 제약이라고 하는 Bounded quantification|유계 정량화영어 개념을 채택했다. 1990년대 Haskell은 임시 다형성과 제네릭스를 융합한 타입 클래스를 고안했다. 2003년 Scala는 서브타이핑, 제네릭스, 공변성과 반변성을 도입했다.

3. 다형성의 종류

크리스토퍼 스트레이치는 다형성을 크게 임시 다형성과 매개변수 다형성으로 분류했다.[5] 피터 웨그너와 루카 카르델리는 1985년 논문에서 상속을 모델링하기 위해 포함 다형성이라는 용어를 도입했으며, 이를 구현한 최초의 프로그래밍 언어로 시뮬라를 언급했다.[1]

다형성은 다음과 같이 분류할 수 있다.


  • 임시 다형성 (Ad hoc polymorphism): 함수 오버로딩이나 연산자 오버로딩처럼, 함수나 연산자가 여러 타입에 적용될 수 있지만 각 타입에 따라 다르게 동작하는 방식이다.
  • 매개변수 다형성 (Parametric polymorphism): 함수나 데이터 형식이 특정 타입에 의존하지 않고 여러 타입을 균일하게 처리할 수 있도록 일반화하는 방식이다. 제네릭이나 C++템플릿이 대표적인 예이다.
  • 서브타입 다형성 (Subtype polymorphism) (포함 다형성): 객체 지향 프로그래밍에서 상속을 통해 하위 클래스의 객체가 상위 클래스의 객체처럼 동작할 수 있는 방식이다. 리스코프 치환 원리에 따라 하위 타입 객체는 상위 타입 객체가 사용되는 곳에 문제없이 사용될 수 있다.


암묵적 타입 변환을 "강제 다형성"이라고 부르기도 한다.[1][6]

3. 1. 임시 다형성 (Ad hoc polymorphism)

크리스토퍼 스트레이치는 서로 다른 유형의 인수에 적용될 수 있지만, 적용되는 인수의 유형에 따라 다르게 동작하는 다형 함수를 지칭하기 위해 '애드혹 다형성'이라는 용어를 사용했다.[5] 이는 함수 오버로딩 또는 연산자 오버로딩으로도 알려져 있다. 여기서 "애드혹"이라는 용어는 이 형태의 다형성이 타입 시스템의 근본적인 특징이 아님을 의미하는 것으로, 비하적인 의미는 아니다.

아래 자바 예제에서 `Add` 함수는 호출 시 두 가지 유형 (정수와 문자열)에 대해 일반적으로 작동하는 것처럼 보이지만, 컴파일러는 이를 두 개의 완전히 다른 함수로 간주한다.



class AdHocPolymorphic {

public String add(int x, int y) {

return "Sum: "+(x+y);

}

public String add(String name) {

return "Added "+name;

}

}

public class adhoc {

public static void main(String[] args) {

AdHocPolymorphic poly = new AdHocPolymorphic();

System.out.println( poly.add(1,2) ); // prints "Sum: 3"

System.out.println( poly.add("Jay") ); // prints "Added Jay"

}

}



동적 타이핑 언어에서는 호출해야 하는 올바른 함수가 런타임에만 결정될 수 있으므로 상황이 더 복잡할 수 있다.

암묵적 타입 변환은 "강제 다형성"이라고 하는 다형성의 한 형태로 정의되기도 한다.[1][6]

함수나 연산자의 다중 정의처럼, 같은 이름으로 타입이 다른 인수에 적용할 수 있으며, 그 동작은 인수의 타입에 따라 다른 함수 다형성을 "임시 다형성"이라고 한다. 다음 C++(C++)의 예에서는, `Add` 함수는 호출 측에서는 다양한 타입에 대해 총괄적으로 동작하는 것처럼 보이지만, 컴파일러 입장에서 보면 이들은 완전히 별개의 두 함수이다.



#include

#include

int Add(int x, int y) {

return x + y;

}

std::string Add(const std::string& s1, const std::string& s2) {

return s1 + s2;

}

int main() {

std::cout << Add(1, 2) << std::endl; // "3" 이 출력된다.

std::cout << Add("Hello, ", "World!") << std::endl; // "Hello, World!" 가 출력된다.

}



동적 타이핑 언어에서는 실행되어야 하는 올바른 함수가 실행 시점까지 결정되지 않을 수 있다는 점에서, 상황은 더욱 복잡해질 수 있다. 암묵적 타입 변환도 타입 강제 다형성(coercion polymorphism)으로 임시 다형성의 한 형태로 정의된다.[18][20]

3. 2. 매개변수 다형성 (Parametric polymorphism)

매개변수 다형성은 함수나 데이터 형식이 타입에 의존하지 않고 값을 균일하게 처리할 수 있도록 일반화하는 방법이다.[7] 이는 정적 형식 안전성을 유지하면서 언어를 더 표현력 있게 만드는 방법이다.

매개변수 다형성 개념은 데이터 형식과 함수 모두에 적용된다. 서로 다른 형식의 값으로 평가되거나 적용될 수 있는 함수를 ''다형성 함수''라고 한다. 임의의 형식의 요소를 가진 리스트처럼 일반화된 형식으로 나타낼 수 있는 데이터 형식은 ''다형성 데이터 형식''으로 지정된다.

매개변수 다형성은 함수형 프로그래밍에서 자주 사용되며, 종종 "다형성"이라고 불린다. 다음 Haskell 예제는 매개변수화된 리스트 데이터 형식과 이에 대한 두 개의 매개변수 다형성 함수를 보여준다.



data List a = Nil | Cons a (List a)

length :: List a -> Integer

length Nil = 0

length (Cons x xs) = 1 + length xs

map :: (a -> b) -> List a -> List b

map f Nil = Nil

map f (Cons x xs) = Cons (f x) (map f xs)



매개변수 다형성은 여러 객체 지향 언어에서도 사용할 수 있다. 예를 들어, C++D템플릿, 또는 C#, Delphi, Java 및 Go의 제네릭이 있다.



class List {

class Node {

T elem;

Node next;

}

Node head;

int length() { ... }

}

List map(Func f, List xs) {

...

}



존 C. 레이놀즈와 장-이브 지라르는 이러한 다형성 개념을 람다 계산법의 확장(다형성 람다 계산법 또는 시스템 F)으로 공식적으로 개발했다.

3. 3. 서브타입 다형성 (Subtyping polymorphism)

객체 지향 프로그래밍 언어는 ''서브클래스'' (''상속''이라고도 함)을 사용하여 서브타입 다형성을 제공한다. 일반적인 구현에서 각 클래스는 클래스 인터페이스의 다형성 부분을 구현하는 함수의 테이블인 ''가상 함수 테이블''(줄여서 ''vtable'')을 포함하고, 각 객체는 해당 클래스의 vtable에 대한 포인터를 포함하며, 다형성 메서드가 호출될 때마다 이 테이블을 참조한다. 이 메커니즘은 다음의 예이다.

  • ''후기 바인딩'', 가상 함수 호출은 호출 시점까지 바인딩되지 않기 때문이다.
  • ''단일 디스패치''(즉, 단일 인자 다형성), 가상 함수 호출은 첫 번째 인자(this 객체)가 제공하는 vtable을 살펴보기만 하면 바인딩되므로 다른 인자의 런타임 유형은 완전히 관련이 없기 때문이다.


Common Lisp과 같은 일부 시스템은 메서드 호출이 ''모든'' 인자에서 다형성인 ''다중 디스패치''를 제공한다.

일부 언어는 특정 다형성 사례에서 사용할 수 있는 유형의 범위를 제한하기 위해 ''서브타이핑''(또는 ''서브타입 다형성'' 또는 ''포함 다형성'')의 개념을 사용한다. 이러한 언어에서 서브타이핑을 사용하면 특정 유형 ''T''의 객체를 받아들이도록 함수를 작성할 수 있지만, ''T''의 서브타입인 유형 ''S''에 속하는 객체를 전달하더라도 올바르게 작동한다 ( 리스코프 치환 원리에 따르면). 이 유형 관계는 S <: T 로 표기될 수 있다. 반대로, ''T''는 ''S''의 ''슈퍼타입''이라고 하며 T :> S 로 표기한다. 서브타입 다형성은 일반적으로 동적으로 해결된다.

다음은 Java 예제이다. 고양이와 개는 애완동물의 서브타입으로 만들어진다. letsHear() 절차는 애완동물을 받아들이지만 서브타입이 전달되더라도 올바르게 작동한다.

```java

abstract class Pet {

abstract String speak();

}

class Cat extends Pet {

String speak() {

return "Meow!";

}

}

class Dog extends Pet {

String speak() {

return "Woof!";

}

}

static void letsHear(final Pet pet) {

println(pet.speak());

}

static void main(String[] args) {

letsHear(new Cat());

letsHear(new Dog());

}

3. 4. 로 다형성 (Row polymorphism)

행 다형성
[8]서브타이핑과 유사하지만, 구별되는 개념이다. 이는 구조적 타입을 다루며, 나머지 타입 정보를 잃지 않으면서 특정 속성을 가진 타입의 모든 값을 사용할 수 있게 해준다. 구조적 타이핑의 다형성은 로 다형성으로 분류될 수 있으며[22], 덕 타이핑 설명에도 적합하다.

일본어에서는 행 다형[23] 또는 열 다형[24]이라고 번역되기도 한다.

3. 5. 폴리타이피즘 (Polytypism)

폴리타이피즘은 매개변수 다형성에서 파생된 개념이다. 매개변수 다형성에서는 형이 형 변수를 포함하는 반면, 폴리타이피즘에서는 형이 컨테이너를 착탈한다는 개념을 사용한다. 컨테이너의 착탈은 범주론에서의 함자와 유사하다. 폴리타이피즘은 제네릭 프로그래밍을 설명하는 다형성으로 취급된다.[9]

3. 6. 랭크 다형성 (Rank polymorphism)

랭크 다형성은 배열 프로그래밍 언어, 예를 들어 APL의 주요 특징 중 하나이다. 랭크 다형성 프로그래밍 모델의 핵심은 모든 연산을 임의의 차원을 가진 배열에서 사용할 수 있는 집계 연산으로 암묵적으로 처리하는 것이다.[10] 즉, 랭크 다형성은 함수가 임의의 모양과 크기의 배열에서 작동하도록 정의할 수 있게 해준다.

4. 다형성의 구현

크리스토퍼 스트레이치는 다형성을 구현 시점에 따라 정적 다형성과 동적 다형성으로 구분했다.[5] 정적 다형성은 컴파일 시점에 구현 방식이 결정되어 실행 속도가 빠르지만 유연성이 낮고, 동적 다형성은 런타임 시점에 결정되어 유연하지만 실행 속도가 느리다.[1][5]

4. 1. 정적 다형성과 동적 다형성

크리스토퍼 스트레이치는 다형성을 정적 다형성과 동적 다형성으로 구분했다.[5] 정적 다형성은 컴파일 시점에 구현 방식이 결정되고, 동적 다형성은 런타임 시점에 결정된다.

정적 다형성은 실행 속도가 빠르지만 유연성이 낮다. 임시 다형성과 매개변수 다형성이 이에 속한다.[5]

동적 다형성은 유연하지만 실행 속도가 느리다. 서브타입 다형성이 대표적인 예시다.[1]

일반적으로 서브타입 다형성은 동적으로 구현되지만, 템플릿 메타프로그래밍의 기묘하게 재귀적인 템플릿 패턴을 사용하면 정적으로 구현할 수 있다. 이를 통해 유연성과 성능을 모두 확보할 수 있다.

5. 단태성 (Monomorphism)

단형성 체계를 가진 프로그램 언어에서 함수는 각각 한 가지 의미로 식별되는 이름과 결합되어 있어, 다른 동작을 구현하기 위해서는 다른 이름을 써야 한다.

예를 들어 어떤 값을 문자열 형식으로 변환하는 단순한 경우를 생각해보자. 다형성 형태 체계를 가지지 못한 언어에서는 다음과 같이 개별 함수로 되어 있을 것이다.


  • 숫자를 문자열로 바꾸는 경우



string = StringFromNumber(number);


  • 날짜를 문자열로 바꾸는 경우



string = StringFromDate(date);



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

  • 숫자를 문자열로 바꾸는 경우



string = number.StringValue();


  • 날짜를 문자열로 바꾸는 경우



string = date.StringValue();



물론 `StringValue` 메소드의 정의는 형태별로 따로 수행되어야 하기 때문에 전체적으로 코드의 분량이 감소하는 것은 아니다. (다만 상속에 의한 재사용은 있을 수 있다.) 또 무엇이 '올바른 동작'인지는 객체의 설계에 따라 달라질 수 있으므로, 다형성을 잘 다루려면 체계 전체를 파악하는 뛰어난 설계 능력이 요구된다. 다형성의 반대말로서 '''단태성''' (monomorphism, 単態性, 단상성)이라는 단어가 사용될 수 있다.

참조

[1] 학술지 On understanding types, data abstraction, and polymorphism http://lucacardelli.[...] 1985-12
[2] 웹사이트 Bjarne Stroustrup's C++ Glossary http://www.stroustru[...] 2007-02-19
[3] 웹사이트 Polymorphism https://docs.oracle.[...] Oracle 2021-09-08
[4] 서적 Object-Oriented Analysis and Design with Applications Pearson Education 2007
[5] 학술지 Fundamental Concepts in Programming Languages 2000
[6] 서적 Computer Science Handbook https://books.google[...] Taylor & Francis 2004
[7] 서적 Types and Programming Languages MIT Press 2002
[8] 간행물 Type inference for record concatenation and multiple inheritance 1989-06
[9] 서적 Practical Aspects of Declarative Languages: 4th International Symposium Springer 2002
[10] arXiv The semantics of rank polymorphism 2019
[11] 웹사이트 How Swift Achieved Dynamic Linking Where Rust Couldn't https://gankra.githu[...]
[12] 웹사이트 Bjarne Stroustrup's C++ Glossary http://www.stroustru[...] 2017-03-08
[13] 학술지 On understanding types, data abstraction, and polymorphism http://lucacardelli.[...] 1985-12
[14] 웹사이트 Polymorphism https://docs.oracle.[...] Oracle 2021-09-08
[15] 서적 Object-Oriented Analysis and Design with Applications Pearson Education 2007
[16] 학술지 光の非視覚的作用と概日リズム : 生理的多型性へのアプローチ(生理人類学のキーワード"生理的多型性"の本質に迫る) https://cir.nii.ac.j[...] 2013
[17] 문서 C. Strachey – Fundamental Concepts in Programming Languages http://www.itu.dk/co[...]
[18] 학술지 On understanding types, data abstraction, and polymorphism http://lucacardelli.[...] ACM 1985-12
[19] 웹사이트 ポリタイピックプログラミング(polytypic programming)はジェネリックプログラミングと同一視されることがある。 https://link.springe[...] SpringerLink
[20] 서적 Computer Science Handbook, Second Edition https://books.google[...] Taylor & Francis 2004-06-28
[21] 서적 Types and Programming Languages. MIT Press. 2002
[22] 웹사이트 Objects and Aspects: Row Polymorphism https://www.cs.cmu.e[...] Neel Krishnaswami, Department of Computer Science, Carnegie Mellon University
[23] 웹사이트 実例によるPureScript https://aratama.gith[...]
[24] 웹사이트 OCamlで構築するモダンWeb:型付きHTML5プログラミングの実際 http://proofcafe.org[...] 有限会社ITプランニング | 今井 敬吾



본 사이트는 AI가 위키백과와 뉴스 기사,정부 간행물,학술 논문등을 바탕으로 정보를 가공하여 제공하는 백과사전형 서비스입니다.
모든 문서는 AI에 의해 자동 생성되며, CC BY-SA 4.0 라이선스에 따라 이용할 수 있습니다.
하지만, 위키백과나 뉴스 기사 자체에 오류, 부정확한 정보, 또는 가짜 뉴스가 포함될 수 있으며, AI는 이러한 내용을 완벽하게 걸러내지 못할 수 있습니다.
따라서 제공되는 정보에 일부 오류나 편향이 있을 수 있으므로, 중요한 정보는 반드시 다른 출처를 통해 교차 검증하시기 바랍니다.

문의하기 : help@durumis.com