다형성 (컴퓨터 과학)

Polymorphism (computer science)

프로그래밍 언어 이론과 유형 이론에서, 다형성은 다른 유형[1] 실체에 대한 단일 인터페이스를 제공하거나 여러 다른 [2]유형을 나타내기 위해 단일 기호를 사용하는 것입니다.그 개념은 생물이나 종이 많은 다른 형태나 [3]단계를 가질 수 있는 생물학의 원리에서 차용되었다.

가장 일반적으로 인식되는 다형성의 주요 클래스는 다음과 같습니다.

  • 애드혹 다형성: 개별적으로 지정된 유형의 임의의 세트에 대해 공통 인터페이스를 정의합니다.
  • 파라메트릭 다형성: 구체적인 유형을 지정하지 않고 대신 모든 유형을 대체할 수 있는 추상 기호를 사용합니다.
  • 서브타이핑(서브타입 다형성 또는 포함 다형성이라고도 함): 이름이 일반적인 [4]슈퍼클래스와 관련된 다양한 클래스의 인스턴스를 나타내는 경우.

역사

다형식 시스템에 대한 관심은 1960년대에 크게 발전했고, 실용적 구현은 10년 말에 나타나기 시작했다.애드혹 다형성파라메트릭 다형성원래 크리스토퍼 스트레이시의 프로그래밍 [5]언어 기본 개념에서 설명되었으며, 다형성의 "두 가지 주요 클래스"로 나열됩니다.애드혹 다형성은 Algol 68의 특징이었고, 파라메트릭 다형성은 ML 타입 시스템의 핵심 특징이었다.

1985년의 논문에서, Peter Wegner와 Luca Cardelli는 모델 서브타입과 [2]상속을 위해 포함 다형이라는 용어를 도입했고, 이를 구현한 최초의 프로그래밍 언어로 Simula를 인용했다.

종류들

애드혹 다형

Christopher Stracey는 다양한 유형의 인수에 적용할 수 있지만 적용되는 인수의 유형에 따라 다르게 동작하는 다형함수(함수 오버로드 또는 연산자 [5]오버로드라고도 함)를 나타내기 위해 애드혹 다형함수라는 용어를 선택했습니다. 문맥에서 "애드혹"이라는 용어는 경멸을 의도하는 것이 아니라 단지 이런 유형의 다형성이 유형 시스템의 근본적인 특징이 아니라는 사실을 의미한다.다음 Pascal/Delphi 예제에서는Add호출을 볼 때 함수는 일반적으로 다양한 유형에서 작동하는 것처럼 보이지만 컴파일러에 의해 모든 의미와 목적에 대해 완전히 다른 두 가지 함수로 간주됩니다.

프로그램. 애드혹;  기능. 더하다(x, y : 정수) : 정수; 시작한다.     더하다 := x + y 끝.;  기능. 더하다(s, t : 스트링) : 스트링; 시작한다.     더하다 := 콘캣(s, t) 끝.;  시작한다.     쓰기(더하다(1, 2));                   (* "3" * 인쇄)     쓰기(더하다('안녕하세요', 엄마들!));    (* "안녕, 포유동물!"*) 끝.. 

동적으로 입력된 언어에서는 실행 시에만 호출해야 하는 올바른 함수를 결정할 수 있기 때문에 상황이 더 복잡해질 수 있습니다.

암묵적 유형 변환은 또한 "공작 다형성"[2][6]이라고 불리는 다형성의 한 형태로 정의되었습니다.

파라메트릭 다형

파라메트릭 다형성을 사용하면 함수나 데이터 유형을 범용적으로 작성할 수 있으므로 유형에 [7]따라 을 균일하게 처리할 수 있습니다.파라메트릭 다형성은 완전한 정적 유형 안전성을 유지하면서 언어를 더 표현하기 위한 방법입니다.

파라메트릭 다형성의 개념은 데이터 유형함수 모두에 적용됩니다.다른 유형의 값을 평가할 수 있거나 적용할 수 있는 함수를 다형함수라고 합니다.범용형(예를 들어 임의의 유형의 요소를 가진 리스트)으로 보일 수 있는 데이터 타입은 그러한 전문화가 이루어지는 범용형처럼 다형 데이터 타입으로 지정된다.

파라메트릭 다형성은 함수 프로그래밍에서 흔히 볼 수 있으며, 여기서 간단히 "다형성"이라고 한다.Haskell의 다음 예시는 파라미터화된 리스트 데이터 타입과 이들 데이터 타입에 파라미터화된2개의 폴리모픽 함수를 나타내고 있습니다.

데이터. 목록. a = 제로   단점 a (목록. a)  길이 :: 목록. a -> 정수 길이 제로         = 0 길이 (단점 x xs) = 1 + 길이 xs  지도 :: (a -> b) -> 목록. a -> 목록. b 지도 f 제로         = 제로 지도 f (단점 x xs) = 단점 (f x) (지도 f xs) 

파라메트릭 다형성은 여러 객체 지향 언어에서도 사용할 수 있습니다.예를 들어 C++ 및 D의 템플릿 또는 C#, Delphi, Java 및 Go의 범용 이름 아래에 있는 템플릿은 다음과 같습니다.

학급 목록.< >T> {     학급 노드< >T> {         T 일람;         노드< >T> 다음 분.;     }     노드< >T> 머리;     인트 길이() { ... } }  목록.< >B> 지도(펑크< >A, B> f, 목록.< >A> xs) {     ... } 

C. 레이놀즈(그리고 나중에 장 이브 지라르)는 람다 미적분(다형 람다 미적분 또는 시스템 F)의 확장으로서 다형성의 개념을 공식적으로 발전시켰다.모든 파라메트릭 다형 함수는 반드시 그것이 할 수 있는 일에 제한을 받고, 그 값이 아닌 데이터의 모양에 대해 작업하기 때문에 파라메트릭 함수의 개념이 생겨납니다.

서브타이핑

어떤 언어들은 특정 다형성 경우에 사용될 수 있는 유형의 범위를 제한하기 위해 서브타이핑(아형 다형성 또는 포함 다형성이라고도 함) 개념을 사용한다.이러한 언어에서 서브타이핑은 특정 타입 T의 오브젝트를 취하기 위해 함수를 쓸 수 있지만 (Liskov 치환 원리에 따라) T의 서브타입 S에 속하는 오브젝트를 통과시켰을 경우 정상적으로 동작할 수도 있습니다.이 타입의 관계는 S <: T라고 하는 경우도 있습니다.반대로 T는 S의 슈퍼 타입이라고 합니다.서브 타입의 다형성은 일반적으로 동적으로 해결됩니다(아래 참조).

다음 Java 예제에서는 고양이와 개를 동물의 하위 유형으로 만듭니다.순서letsHear()는 동물을 받아들이지만 서브타입이 전달된 경우에도 올바르게 동작합니다.

추상적인 학급 동물 {     추상적인 스트링 말해라.(); }  학급 고양이 확장 동물 {     스트링 말해라.() {         돌아가다 "야옹!";     } }  학급  확장 동물 {     스트링 말해라.() {         돌아가다 "우~";     } }  정적인 공백 렛츠히어(최종 동물 a) {     인쇄(a.말해라.()); }  정적인 공백 주된(스트링[] args) {     렛츠히어(신규 고양이());     렛츠히어(신규 ()); } 

다른 예에서는 Number, Rational Integer가 Number :> Rational 및 Number :> Integer같은 유형인 경우, Number를 취득하도록 기술된 함수는 Number를 전달했을 때와 마찬가지로 Integer 또는 Rational을 전달했을 때 동일하게 기능합니다.객체의 실제 유형은 클라이언트에서 블랙박스로 숨길 수 있으며 객체 ID를 통해 액세스할 수 있습니다.실제로 Number 유형이 추상적인 경우 가장 파생된 유형이 Number인 개체를 손에 넣을 수 없을 수도 있습니다(추상 데이터 유형, 추상 클래스 참조).이러한 특정 유형의 계층 구조는 특히 스킴 프로그래밍 언어의 컨텍스트에서 숫자 타워로 알려져 있으며, 일반적으로 더 많은 유형을 포함합니다.

객체 지향 프로그래밍 언어는 하위 분류(상속이라고도 함)를 사용하여 하위 유형 다형성을 제공합니다.일반적인 구현에서 각 클래스는 가상 테이블(클래스 인터페이스의 다형성 부분을 구현하는 함수의 테이블)이라고 불리는 것을 포함하며, 각 개체는 클래스의 "vtable"에 대한 포인터를 포함합니다.이 포인터는 다형성 메서드가 호출될 때마다 참조됩니다.이 메커니즘의 예는 다음과 같습니다.

  • 호출 시까지 가상 함수 호출이 바인딩되지 않기 때문에 레이트바인딩.
  • 단일 디스패치(즉, 단일 패킷 다형성)는 가상 함수 호출이 첫 번째 인수에 의해 제공되는 vtable을 통해 단순히 바인드되기 때문입니다.thisobject)는 다른 인수의 런타임 유형은 전혀 관련이 없습니다.

다른 대부분의 인기 있는 객체 시스템도 마찬가지입니다.단, Common Lisp Object System 의 일부에서는 여러 디스패치를 제공합니다.이 경우 메서드콜은 모든 인수로 다형성이 됩니다.

파라메트릭 다형성과 서브타이핑 사이의 상호작용은 분산과 유계 정량화의 개념으로 이어진다.

행 다형

행 다형성은[8] 서브타이핑과 유사하지만 다른 개념입니다.구조적인 유형을 다루고 있습니다.이 옵션을 사용하면 나머지 유형 정보를 잃지 않고 유형이 특정 속성을 가진 모든 값을 사용할 수 있습니다.

폴리타이프리즘

관련 개념은 폴리타입(또는 데이터 타입의 범용성)입니다.폴리타입 함수는 폴리모픽 함수보다 일반적이며, 이러한 함수에서는 "특정 데이터 타입에 대해 고정 애드혹 케이스를 제공할 수 있지만 애드혹 조합기는 없다"[9]고 한다.

구현 측면

정적 및 동적 다형성

다형성은 구현 선택 시 정적(컴파일 시) 또는 동적(실행 시 일반적으로 가상 기능을 통해)으로 구분할 수 있습니다.이를 각각 정적 디스패치 및 동적 디스패치라고 하며, 이에 따라 대응하는 형태의 다형성을 정적 다형성동적 다형성이라고 합니다.

동적 디스패치 오버헤드가 없기 때문에 정적 다형성은 더 빨리 실행되지만 추가 컴파일러 지원이 필요합니다.또한 정적 다형성을 통해 컴파일러(특히 최적화용), 소스 코드 분석 도구 및 휴먼 리더(프로그래머)에 의한 정적 분석이 향상됩니다.동적 다형성은 더 유연하지만 더 느립니다. 예를 들어 동적 다형성을 사용하면 덕 타이핑이 가능하며 동적으로 링크된 라이브러리는 개체에서 전체 유형을 인식하지 못하고 작동할 수 있습니다.

정적 다형성은 일반적으로 임시 다형성과 파라메트릭 다형성에서 발생하는 반면 동적 다형은 아형 다형성에서 흔히 발생한다.그러나 템플릿 메타프로그래밍(이상하게 반복되는 템플릿 패턴)을 보다 정교하게 사용함으로써 서브타이핑에 의한 정적 다형성을 실현할 수 있습니다.

라이브러리를 통해 다형성이 노출되면 공유 객체가 구축될 때 파라미터의 종류를 알 수 없기 때문에 동적 라이브러리에서 정적 다형성이 불가능하게 됩니다.C++나 Rust와 같은 언어들은 단일화된 템플릿을 사용하는 반면, Swift 프로그래밍 언어는 기본적으로 이러한 라이브러리를 위한 애플리케이션 바이너리 인터페이스를 구축하기 위해 동적 디스패치를 광범위하게 사용합니다.그 결과 런타임 [10]오버헤드를 희생하면서 시스템 크기를 줄이기 위해 더 많은 코드를 공유할 수 있습니다.

「 」를 참조해 주세요.

레퍼런스

  1. ^ Bjarne Stroustrup (February 19, 2007). "Bjarne Stroustrup's C++ Glossary". polymorphism – providing a single interface to entities of different types.
  2. ^ a b c Cardelli, Luca; Wegner, Peter (December 1985). "On understanding types, data abstraction, and polymorphism" (PDF). ACM Computing Surveys. 17 (4): 471–523. CiteSeerX 10.1.1.117.695. doi:10.1145/6041.6042. S2CID 2921816.: "다형 유형은 여러 유형의 값에 연산을 적용할 수 있는 유형입니다."
  3. ^ "Polymorphism". The Java™ Tutorials: Learning the Java Language: Interfaces and Inheritance. Oracle. Retrieved 2021-09-08.
  4. ^ Conallen, J.; Engle, M.; Houston, K.; Maksimchuk, R.; Young, B.; Booch, G. (2007). Object-Oriented Analysis and Design with Applications (3rd ed.). Pearson Education. ISBN 9780132797443.
  5. ^ a b Strachey, Christopher (2000). "Fundamental Concepts in Programming Languages". Higher-Order and Symbolic Computation. 13 (1/2): 11–49. CiteSeerX 10.1.1.332.3161. doi:10.1023/A:1010000313106. ISSN 1573-0557. S2CID 14124601.
  6. ^ Tucker, Allen B. (2004). Computer Science Handbook (2nd ed.). Taylor & Francis. pp. 91–. ISBN 978-1-58488-360-9.
  7. ^ Pierce, B.C. (2002). "23.2 Varieties of Polymorphism". Types and Programming Languages. MIT Press. pp. 340–1. ISBN 9780262162098.
  8. ^ Wand, Mitchell (June 1989). "Type inference for record concatenation and multiple inheritance". Proceedings. Fourth Annual Symposium on Logic in Computer Science. pp. 92–97. doi:10.1109/LICS.1989.39162.
  9. ^ Lämmel, Ralf; Visser, Joost (2002). "Typed Combinators for Generic Traversal". Practical Aspects of Declarative Languages: 4th International Symposium. Springer. pp. 137–154, See p. 153. CiteSeerX 10.1.1.18.5727. ISBN 354043092X.
  10. ^ Beingessner, Alexis. "How Swift Achieved Dynamic Linking Where Rust Couldn't".

외부 링크