복수 디스패치

Multiple dispatch

멀티 디스패치 또는 멀티 모드란 일부 프로그래밍 언어의 기능으로, 함수 또는 메서드는 런타임(다이나믹) 타입에 따라 동적으로 디스패치할 수 있으며, 보다 일반적인 경우에는 여러 [1]인수의 다른 속성을 기준으로 디스패치할 수 있습니다.이는 함수 또는 메서드콜이 메서드가 호출된 객체의 파생 유형을 기반으로 동적으로 디스패치되는 싱글디스패치 다형성의 일반화입니다.여러 디스패치는 1개 또는 여러 인수의 특성을 조합하여 동적 디스패치를 구현 기능 또는 메서드로 라우팅합니다.

디스패치에 대해서

컴퓨터 소프트웨어 개발자는 일반적으로 소스 코드를 서브루틴, 프로시저, 서브프로그램, 함수 또는 메서드라고 불리는 다양한 이름의 블록으로 구성합니다.함수의 코드는 해당 이름을 참조하는 코드를 호출하여 실행됩니다.이것에 의해, 일시적으로 호출된 함수에 제어가 전송 됩니다.함수의 실행이 완료되면, 통상은 참조에 이은 호출자의 명령으로 제어가 되돌려집니다.

함수명은 보통 함수의 목적을 설명하기 위해 선택됩니다.여러 함수에 동일한 이름을 붙이는 것이 바람직할 수 있습니다.개념적으로는 유사한 작업을 수행하지만 입력 데이터의 유형이 다르기 때문입니다.이 경우 함수 호출 사이트에서의 이름 참조는 실행하는 코드 블록을 식별하기에 충분하지 않다.대신 함수 호출에 대한 인수의 수와 유형은 여러 함수 구현 중에서 선택하기 위해 사용됩니다.

보다 전통적인, 즉 싱글 디스패치 오브젝트 지향 프로그래밍 언어에서는 메서드(Smalltalk에서 메시지송신하고 C++에서 멤버 함수를 호출)를 호출할 때, 그 인수 중 하나가 특별히 처리되어 그 이름의 (잠재적으로 많은) 클래스의 메서드를 적용할지를 결정하기 위해 사용된다.많은 언어에서 특수 인수는 구문적으로 나타납니다.예를 들어 메서드 호출을 할 때 많은 프로그래밍 언어가 특수 인수를 점 앞에 둡니다.special.method(other, arguments, here),하도록lion.sound()굉음을 내는 반면sparrow.sound()삑삑거리는 소리가 나요.

반면 여러 디스패치가 있는 언어에서는 단순히 함수 호출의 수와 유형에 일치하는 인수를 가진 메서드가 선택됩니다.특정 콜에서 실행되는 함수 또는 메서드를 소유하는 특별한 인수는 없습니다.

Common Lisp Object System(CLOS; 공통 리스프 오브젝트 시스템)은 여러 디스패치의 초기 및 잘 알려진 예입니다.

데이터형

컴파일데이터 유형을 구별할 수 있는 언어를 사용할 경우 다른 언어 중에서 선택할 수 있습니다.컴파일 시간 선택을 위해 이러한 대체 함수를 생성하는 행위를 보통 함수 오버로드라고 합니다.

데이터 타입 식별을 실행 시간(, 레이트바인딩)까지 연기하는 프로그래밍 언어에서는 동적으로 결정된 함수 인수의 유형에 기초하여 대체 함수 중에서 선택해야 합니다.대체 구현이 이러한 방식으로 선택되는 함수를 일반적으로 다중 방식이라고 합니다.

함수 콜의 동적 디스패치에는 몇 가지 런타임 비용이 발생합니다.일부 [citation needed]언어에서는 컴파일러가 특정 함수 호출에 컴파일 시간 선택을 적용할 수 있는지 또는 더 느린 실행 시간 디스패치가 필요한지 여부를 결정함에 따라 오버로드와 멀티 ethod의 구분이 모호해질 수 있습니다.

실제 사용

Muschevici [2]등은 실제로 다중 디스패치가 사용되는 빈도를 추정하기 위해 동적 디스패치를 사용하는 프로그램을 연구했다.이들은 주로 컴파일러가 6개 언어로 작성된 9개 애플리케이션을 분석했습니다.Common Lisp Object System, Dylan, Cecil, MultiJava, Diesel 및 Nice.그 결과 범용 함수의 13~32%가 1개의 인수의 다이내믹타입을 사용하고 있으며, 그 중 2.7~6.5%가 복수의 인수의 다이내믹타입을 사용하고 있는 것을 알 수 있습니다.일반 함수의 나머지 65-93%는 하나의 구체적인 방법(오버라이더)을 가지고 있기 때문에, 그 인수의 동적 유형을 사용하는 것으로 간주되지 않는다.또한, 연구는 일반 기능의 2-20%가 2개, 3-6%가 3개의 구체적인 기능 구현을 가지고 있다고 보고했다.콘크리트 오버라이더가 많은 기능에서는 수치가 급격히 감소합니다.

다중 디스패치는 Julia에서 훨씬 더 많이 사용됩니다. Julia에서는 다중 디스패치가 언어의 원점에서 중앙 설계 개념이었습니다.일반 함수당 평균 메서드 수에 대해 Muschevici와 동일한 통계를 수집하면 Julia 표준 라이브러리는 다른 표준 라이브러리보다 두 배 이상의 오버로드를 사용하는 것으로 나타났습니다.Muschevici가 분석한 언어, 바이너리 [3]연산자의 경우 10회 이상 분석했습니다.

이들 문서의 데이터는 다음 표에 요약되어 있습니다.여기서 디스패치 비율은DR일반적인 함수별 평균 메서드 수; 선택 비율CR(다수의 방법으로 함수의 빈도를 더 잘 측정하기 위해)[2][3] 방법 수의 제곱 평균 및 전문화 정도DoS는 메서드별 유형별 평균 인수 수(즉, 디스패치되는 인수 수)입니다.

언어 평균 메서드 수(DR) 선택비(CR) 전문화도(DoS)
세실[2] 2.33 63.30 1.06
공통 리스프(CMU)[2] 2.03 6.34 1.17
공통 리스프(McCLIM)[2] 2.32 15.43 1.17
커먼 리스프(스틸 뱅크)[2] 2.37 26.57 1.11
디젤[2] 2.07 31.65 0.71
딜런(귀디온)[2] 1.74 18.27 2.14
딜런(OpenDylan)[2] 2.51 43.84 1.23
줄리아.[3] 5.86 51.44 1.54
Julia(오퍼레이터 전용)[3] 28.13 78.06 2.01
멀티자바[2] 1.50 8.92 1.02
나이스[2] 1.36 3.46 0.33

이론.

다중 디스패치 언어 이론은 Castagna 등에 의해 늦은 [4][5]바인딩으로 과부하 함수에 대한 모델을 정의함으로써 처음 개발되었다.그것은 객체 지향[6] 언어의 공분산위반 문제에 대한 첫 번째 공식화와 이진법 [7]문제에 대한 해결책을 도출했다.

예를 들어 여러 디스패치와 단일 디스패치의 구별이 명확해질 수 있습니다.(사용자가 볼 수 있는) 물체, 우주선 및 소행성이 있는 게임을 상상해 보십시오.두 물체가 충돌할 때 프로그램은 방금 무엇을 맞췄는지에 따라 다른 작업을 수행해야 할 수 있습니다.

복수 디스패치가 내장된 언어

C#

C#에서는 'dynamic' 키워드를 사용하여 버전4[8](2010년 4월)부터 다이내믹멀티모드의 지원이 도입되었습니다.다음 예시는 멀티유닛을 나타내고 있습니다.다른 많은 스태틱타입 언어와 마찬가지로 C#도 스태틱메서드 [9]오버로드를 지원합니다.마이크로소프트는 개발자들이 대부분의 시나리오에서 [10]동적 타이핑보다 정적 타이핑을 선택할 것으로 예상한다.dynamic 키워드는 COM 오브젝트 및 다이내믹 타입과의 상호 운용성을 지원합니다.NET 언어

다음 예에서는 C#9 및 C#10에서 도입된 기능을 사용하고 있습니다.

사용. 정적인 콜리더 라이브러리;  콘솔.기입선(충돌(신규 소행성(101), 신규 우주선(300))); 콘솔.기입선(충돌(신규 소행성(10), 신규 우주선(10))); 콘솔.기입선(충돌(신규 우주선(101), 신규 우주선(10)));  스트링 충돌(스페이스 오브젝트 x, 스페이스 오브젝트 y) =>     x.크기 > 100 & & y.크기 > 100         ? "대박이다!"         : 충돌 대상(x ~하듯이 역학, y ~하듯이 역학); // 충돌에 대한 동적 디스패치방법 있음  학급 콜리더 라이브러리 {     일반의 정적인 스트링 충돌 대상(소행성 x, 소행성 y) => "a/a";     일반의 정적인 스트링 충돌 대상(소행성 x, 우주선 y) => "a/s";     일반의 정적인 스트링 충돌 대상(우주선 x, 소행성 y) => "s/a";     일반의 정적인 스트링 충돌 대상(우주선 x, 우주선 y) => "s/s"; }  기록. 스페이스 오브젝트(인트 크기); 기록. 소행성(인트 크기) : 스페이스 오브젝트(크기); 기록. 우주선(인트 크기) : 스페이스 오브젝트(크기); 

출력:

대박! a/s s/s 

그루비

Groovy는 범용 Java 호환/인터러블 JVM 언어이며, Java와는 달리 Late Binding/Multiple [11]Dispatch를 사용합니다.

/* 상기 C#의 Groovy 구현 예 레이트 바인딩은 비정적 메서드를 사용하거나 클래스/메서드를 스태틱하게 컴파일할 때 동일하게 동작합니다. (@CompileStatic 주석) */ 학급 프로그램. {     정적인 무효 주된(스트링[] args) {         인쇄 충돌기.충돌하다(신규 소행성(101), 신규 우주선(300))         인쇄 충돌기.충돌하다(신규 소행성(10), 신규 우주선(10))         인쇄 충돌기.충돌하다(신규 우주선(101), 신규 우주선(10))     } }  학급 충돌기 {     정적인 스트링 충돌하다(스페이스 오브젝트 x, 스페이스 오브젝트 y) {         (x.크기 > 100 & & y.크기 > 100) ? "대단한" : 충돌하다(x, y)  // 충돌하는 동적 디스패치방법 있음     }      사적인 정적인 스트링 충돌하다(소행성 x, 소행성 y) { "a/a" }     사적인 정적인 스트링 충돌하다(소행성 x, 우주선 y) { "a/s" }     사적인 정적인 스트링 충돌하다(우주선 x, 소행성 y) { "s/a" }     사적인 정적인 스트링 충돌하다(우주선 x, 우주선 y) { "s/s"} }  학급 스페이스 오브젝트 {     인트 크기     스페이스 오브젝트(인트 크기) { 이것..크기 = 크기 } }  @상속 컨스트럭터 학급 소행성 확장 스페이스 오브젝트 {} @상속 컨스트럭터 학급 우주선 확장 스페이스 오브젝트 {} 

일반적인 리스프

Common Lisp여러 디스패치가 있는 언어에서는 다음과 같은 경우가 있습니다(공통 Lisp의 예를 나타냅니다).

(디프로덕트 충돌하다 ((x 소행성) (y 소행성))   소행성에 충돌하는 소행성에 대처하다   ) (디프로덕트 충돌하다 ((x 소행성) (y 우주선))   소행성과 우주선에 충돌하는 것을 다루다   ) (디프로덕트 충돌하다 ((x 우주선) (y 소행성))   소행성과 충돌하는 우주선을 다루다   ) (디프로덕트 충돌하다 ((x 우주선) (y 우주선))   ;;; 우주선이 우주선을 들이받는 것을 다룬다.   ) 

다른 방법에서도 마찬가지입니다.명시적 테스트 및 "동적 주조"는 사용되지 않습니다.

복수의 디스패치가 존재하는 경우 클래스에서 정의되어 오브젝트에 포함된 메서드의 기존 개념은 매력적이지 않습니다.각 메서드는 위의 메서드와 충돌하여1개가 아닌2개의 다른 클래스에 부가됩니다.따라서 메서드 호출에 대한 특별한 구문은 일반적으로 사라지기 때문에 메서드 호출은 일반적인 함수 호출과 동일하게 보이며 메서드는 클래스가 아닌 일반 함수로 그룹화된다.

줄리아.

Julia는 다중 디스패치를 내장하고 있으며 언어 설계의 [3]핵심입니다.위의 예제의 Julia 버전은 다음과 같습니다.

추상형 스페이스 오브젝트 끝.  구조 소행성 <: 스페이스 오브젝트     크기::내부     끝. 구조 우주선 <: 스페이스 오브젝트     크기::내부                   끝.                충돌하다(::소행성, ::우주선) = "a/s" 충돌하다(::우주선, ::소행성) = "s/a" 충돌하다(::우주선, ::우주선) = "s/s" 충돌하다(::소행성, ::소행성) = "a/a"  충돌하다(x::스페이스 오브젝트, y::스페이스 오브젝트) = (x.크기 > 100 & & y.크기 > 100) ? "대박이다!" : 충돌하다(x, y) 

출력:

줄리아.> 충돌하다(소행성(101), 우주선(300)) "대박이다!"  줄리아.> 충돌하다(소행성(10), 우주선(10)) "a/s"  줄리아.> 충돌하다(우주선(101), 우주선(10)) "s/s" 

라쿠

Raku는 Perl과 마찬가지로 다른 언어의 검증된 아이디어를 사용하고 있으며, 타입 시스템은 여러 디스패치를 통해 컴파일러 측 코드 분석과 강력한 사용자 측 시멘틱스에서 뛰어난 이점을 제공하고 있습니다.

멀티 모드와 멀티 서브를 모두 갖추고 있습니다.대부분의 연산자는 서브루틴이기 때문에 디스패치된 연산자도 여러 개 있습니다.

일반적인 유형의 제약 조건과 함께 매우 특수한 서브루틴을 만들 수 있는 제약 조건도 있습니다.

부분집합 실질량(0 ^..^ Inf; Stellar-Object { has Mass $.mass} 역할이 필요합니다. 메서드 이름()은 Str {...를 반환합니다.};}클래스 소행성 Stellar-Object{메서드 이름{, 소행성의()}}클래스 우주선을 발사하는가 Stellar-Object @)<>이 지워져 망가진 의를 파괴했다;내 해협 @에 피해를 입혔다.)나의 해협{해협달러 .name 돌아선 '을 밝히지 않은 우주선'다.}는다 « 손상된 'collided과의 채로 발견되었습니다 손상된로 ».#우리는 추가 멀티 후보들에게 숫자 비교 oper.ators 숫자 #로 비교하고 있습니다, 오브젝트를 숫자 타입으로 강제하는 것은 의미가 없습니다.# (강제적으로 이러한 연산자를 추가할 필요가 없습니다.) # 완전히 새로운 연산자를 이와 같은 방법으로 정의할 수도 있습니다. multi sub infix:fix <=> " (Stellar-Object:D $a, Stellar-Object:D $b) { $a.mass <=> $b.mass} 다중 서브픽스:disples < ( ( Stellar - Object : D $a, Stellar-Object:D $b ) { $a.mass < $b.mass } 다중 서브픽스: > > ( ( Stellar - Object : )D $a, Stellar-Object:D $b ) { $a.mass > $b.mass } 다중 서브픽스:color == ( (Stellar-Object: ( )D $a, Stellar-Object:D $b ) { $a.mass == $b.mass } # 새로운 다중 디스패처를 정의하고 파라미터에 가지 형식 제약조건을 추가합니다.# 정의하지 않았다면 제약이 없는 범용적인 것을 얻을 수 있었을 것입니다.원시 서브 충돌(Stellar-Object:D $, Stellar-Object:D $ ) {*} # 프로토타입과 같기 때문에 여기서 유형을 반복할 필요가 없습니다.# 'where' 제약은 엄밀히 말하면 시그니처 전체가 아니라 $b에만 적용됩니다.#은 'where의 제약 조건이 `&lt을 사용해 우리가 조금 전에 덧붙였다`연산자 후보. 복수 대신하다 충돌하다(달러,달러 b이달러를<>달러 b){"달러a.name(의@ destroyed.pick()달러로b.name()"이라고 말한다.}다량습니다 대신하다 충돌하다(달러,달러 b이달러 a>달러 b){이전 후보에 대한 인수를 사용#재분배 samewith달러달러 b을 교환했다.}#이되어 있는 a그 fter 첫 번째가지 #가 "where" 제약 조건을 가지고 있기 때문에 #는 서브가 쓰여진 #순서체크됩니다.(이것들은 항상 일치합니다.) 멀티 서브 충돌($a, $b ) { #주문 랜덤화($n1, $n2) = ($b.name, $b.name). #다음후보 에 "$n1 @n1.pick() $n2; }가 될 수 있습니다.roto, #는 앞의 세 가지 유형보다 더 전문화된 유형을 가지고 있기 때문입니다.# 선박의 질량이 동일하지 않으면 대신 후보하나호출됩니다. 다중 서브 충돌(우주선 $a, 우주선 $b){my ($n1, $n2) = (a.name, $b.name.pick); "$n1이 충돌했고, 두  모두 "(@pick. unpick, 'left damaged')"; ##.특히 시그니처 내에 있습니다.# 당신은 심지어 그것들에 대해 제약이 있을있다. 다중 서브 충돌하는 곳 (10): mass=a), 소행성 $ (: mass=b), (: mass=b)) ( 개의 소행성이 충돌하여 질량 {a + $b } , } , } 나의 우주선 $Enterprise = new (1: mass= ) , name ) .엔터프라이즈' 충돌, 소행성.new(:mass(1), $엔터프라이즈, 우주선.new(:mass(1), $엔터프라이즈, 소행성.new(:mass(1)), $엔터프라이즈, 우주선.new(:mass(1)), 소행성.new(mass(5) 충돌.

다중 디스패치 라이브러리를 통한 언어 확장

자바스크립트

언어 정의 또는 구문 수준에서 여러 디스패치를 지원하지 않는 언어에서는 라이브러리 확장을 사용하여 여러 디스패치를 추가할 수 있습니다.JavaScript 및 TypeScript는 구문 수준에서는 멀티패치 기능을 지원하지 않지만 라이브러리를 통해 여러 디스패치를 추가할 수 있습니다.예를 들어 멀티 모드 패키지[12] 여러 디스패치 범용 기능을 구현합니다.

JavaScript의 동적 유형 버전:

수입품 { 복수, 방법 } 부터 '@http/httpseethod'  학급 소행성 {} 학급 우주선 {}  컨스턴트 충돌하다 = 복수(   방법([소행성, 소행성], (x, y) => {     // 소행성과 충돌하는 소행성에 대처합니다.   }),   방법([소행성, 우주선], (x, y) => {     // 소행성 충돌 우주선에 대처하다   }),   방법([우주선, 소행성], (x, y) => {     // 소행성과 충돌하는 우주선 대처   }),   방법([우주선, 우주선], (x, y) => {     // 우주선이 우주선에 충돌하는 것을 다루다   }), ) 

TypeScript의 정적 형식 버전:

'@arrows/multimethod' 클래스 소행성 {} 클래스 우주선 {} 유형 충돌에서 {multi, method, Multi} 가져오기= 다중 & { (x: 소행성, y: 소행성): 보이드(x: 소행성, y: 우주선): 보이드(x: 우주선, y: 우주선): 보이드(x: 우주선): 보이드 } 상시 충돌포함: 충돌= multi(메서드([소행성, 소행성],(), y)=&gt으로;{소행성은 소행성의를 치며//계약}), method([소행성, 우주선],(), y)=>,{소행성 우주선을 치며//계약}), method([우주선, 소행성],(), y)=>,{우주선과//거래 소행성을 때리}), method([우주선, 우주선],(), y)=>, 우주선 안녕과{//거래.공간 tting엉덩이 }), )

파이썬

라이브러리 확장을 사용하여 Python에 여러 디스패치를 추가할 수 있습니다.예를 들어 multimethod[13].py 모듈 및 Python용 CLOS 스타일의 멀티메토드를 제공하는 multimethods[14].py 모듈과 함께 사용하면 언어의 기본 구문이나 키워드를 변경하지 않아도 됩니다.

부터 멀티 모드 수입품 디스패치 부터 game_displays(게임)_filename(실행) 수입품 소행성, 우주선 부터 game_displays(게임)_filename(실행) 수입품 as_func, ss_func, sa_func 충돌하다 = 디스패치() 충돌하다.add_rule(추가 규칙)((소행성, 우주선), as_func) 충돌하다.add_rule(추가 규칙)((우주선, 우주선), ss_func) 충돌하다.add_rule(추가 규칙)((우주선, 소행성), sa_func) 방어하다 aa_func(a, b):     소행성과 소행성이 충돌했을 때의 행동."""     #...새로운 행동을... 충돌하다.add_rule(추가 규칙)((소행성, 소행성), aa_func) 
#...나중에... 충돌하다(물건1, 물건2) 

기능적으로는 CLOS의 예와 매우 비슷하지만 구문은 기존 Python입니다.

Python 2.4 데코레이터사용하여 Guido van Rossum은 단순화된 구문을 사용하여 멀티 ethod의[15] 샘플 구현을 제작했습니다.

@paramethod(소행성, 소행성) 방어하다 충돌하다(a, b):     소행성과 소행성이 충돌했을 때의 행동."""     #...새로운 행동을... @paramethod(소행성, 우주선) 방어하다 충돌하다(a, b):     소행성이 우주선에 충돌했을 때의 행동."""     #...새로운 행동을... #... 기타 멀티모드 규칙을 정의합니다. 

멀티 모드 데코레이터를 정의합니다.

PEACK-Rules 패키지는 위의 [16]예와 유사한 구문을 가진 여러 디스패치를 제공합니다.나중에 PyProtocols로 [17]대체되었다.

Reg 라이브러리는 여러 개의 [18]술어 디스패치도 지원합니다.

복수 디스패치 에뮬레이트

C

C에는 다이내믹디스패치가 없기 때문에 어떤 형태로든 수동으로 실장해야 합니다.종종 열거형은 객체의 하위 유형을 식별하는 데 사용됩니다.동적 디스패치는 함수 포인터 브랜치테이블에서 이 값을 조회함으로써 실행할 수 있습니다.C의 간단한 예를 다음에 나타냅니다.

유형화된 무효 (*콜리젼 케이스)(무효);  무효 충돌_AA(무효) { /* 소행성-아스타로이드 충돌 처리 */ }; 무효 충돌_~하듯이(무효) { /* 소행성-우주선 충돌 처리 */ }; 무효 충돌_SA(무효) { /* 우주선-아스타로이드 충돌 처리 */ }; 무효 충돌_SS(무효) { /* 우주선-우주선 충돌 처리*/ };  유형화된 열거하다 {     물건_아스테로이드 = 0,     물건_스페이스쉽,     물건_카운트 /* 물건 자체가 아니라 물건의 수를 찾는 데 사용 */ } ;  콜리젼 케이스 콜리젼 케이스[물건_카운트][물건_카운트] = {     {&충돌_AA, &충돌_~하듯이},     {&충돌_SA, &충돌_SS} };  무효 충돌하다( a,  b) {     (*콜리젼 케이스[a][b])(); }  인트 주된(무효) {     충돌하다(물건_스페이스쉽, 물건_아스테로이드); } 

C 오브젝트 시스템라이브러리에서는 [19]C는 CLOS와 같은 다이내믹디스패치를 지원합니다.완전히 확장 가능하며 메서드를 수동으로 처리할 필요가 없습니다.다이내믹 메시지(메서드)는 COS 디스패처에 의해 디스패치되며 이는 Objective-C보다 고속입니다.다음으로 COS의 예를 나타냅니다.

#실패하다 <stdio.h> #실패하다 <cos/object.h> #실패하다 < cos / gen / object >h>  // 클래스  디클래스 (소행성) // 데이터 멤버 엔드클래스  디클래스 (우주선) // 데이터 멤버 엔드클래스  // 제네릭  디제너릭 (부울, 충돌하다, _1, _2);  // 멀티 모드  디프로덕트 (부울, 충돌하다, 소행성, 소행성)  // 소행성과 충돌하는 소행성에 대처합니다. 엔드 메서드  디프로덕트 (부울, 충돌하다, 소행성, 우주선)  // 소행성 충돌 우주선에 대처하다 엔드 메서드  디프로덕트 (부울, 충돌하다, 우주선, 소행성)  // 소행성과 충돌하는 우주선 대처 엔드 메서드  디프로덕트 (부울, 충돌하다, 우주선, 우주선)  // 우주선이 우주선에 충돌하는 것을 다루다 엔드 메서드  // 사용 예  인트 주된(무효) {   OBJ a = 새롭다(소행성);   OBJ s = 새롭다(우주선);    인쇄물("<a,a> = %d\n", 충돌하다(a, a));   인쇄물("<a,s> = %d\n", 충돌하다(a, s));   인쇄물("<s,a> = %d\n", 충돌하다(s, a));   인쇄물("<s,s> = %d\n", 충돌하다(s, s));    그리즈(a);   그리즈(s); } 

C++

2021년 현재 C++는 기본적으로 단일 디스패치만을 지원하지만 2007년 [20]Bjarne Strostrup(및 공동작업자)에 의해 다중 방식(복수 디스패치) 추가가 제안되었습니다.이 제한을 회피하는 방법은 방문자 패턴, 동적 캐스트 또는 라이브러리를 사용하는 것과 유사합니다.

 // dynamic_cast를 통한 실행 시간 유형 비교 사용 예   구조  {      가상 무효 충돌하다(& 다른.) = 0;  };   구조 소행성 :  {      무효 충돌하다(& 다른.) {          // dynamic_cast에서 포인터 유형으로 캐스트가 실패하면 NULL을 반환합니다.          // (참조 유형에 대한 dynamic_cast는 장애 시 예외를 발생시킵니다.)          한다면 (자동 소행성 = dynamic_cast< >소행성*>(&다른.)) {              // 소행성-아스타로이드 충돌 처리          } 또 다른 한다면 (자동 우주선 = dynamic_cast< >우주선*>(&다른.)) {              // 소행성-우주선 충돌 처리          } 또 다른 {              // 기본 충돌 처리(여기서)          }      }  };   구조 우주선 :  {      무효 충돌하다(& 다른.) {          한다면 (자동 소행성 = dynamic_cast< >소행성*>(&다른.)) {              // 우주선-아스테로이드 충돌 처리          } 또 다른 한다면 (자동 우주선 = dynamic_cast< >우주선*>(&다른.)) {              // 우주선-우주선 충돌 처리          } 또 다른 {              // 기본 충돌 처리(여기서)          }      }  }; 

또는 포인터 투 포인트룩업 테이블:

#실패하다 <cstdint> #실패하다 <typeinfo> #실패하다 <unordered_map>  학급  {   보호되고 있다:     (표준::uint32_t cid) : 조형물(cid) {}     컨스턴트 표준::uint32_t 조형물; // ID 를 입력합니다.      유형화된 무효 (::*충돌 핸들러)(& 다른.);     유형화된 표준::unordered_map< >표준::uint64_t, 충돌 핸들러> Collision Handler Map;      정적인 무효 add 핸들러(표준::uint32_t id1, 표준::uint32_t id2, 충돌 핸들러 핸들러) {         콜리젼 케이스.삽입하다(Collision Handler Map::value_type(열쇠(id1, id2), 핸들러));     }     정적인 표준::uint64_t 열쇠(표준::uint32_t id1, 표준::uint32_t id2) {         돌아가다 표준::uint64_t(id1) << > 32   id2;     }      정적인 Collision Handler Map 콜리젼 케이스;    일반의:     무효 충돌하다(& 다른.) {         자동 핸들러 = 콜리젼 케이스.발견하다(열쇠(조형물, 다른..조형물));         한다면 (핸들러 != 콜리젼 케이스.끝.()) {             (이것.->*핸들러->둘째)(다른.); // 콜 포인터         } 또 다른 {             // 기본 충돌 처리         }     } };  학급 소행성: 일반의  {     무효 소행성_소행성(& 다른.)   { /*핸들 소행성-아스타로이드 충돌*/ }     무효 우주선_스페이스(& 다른.)  { /*소행성-우주선 충돌*/}    일반의:     소행성(): (cid) {}     정적인 무효 초기 케이스();     정적인 컨스턴트 표준::uint32_t cid; };  학급 우주선: 일반의  {     무효 소행성_소행성(& 다른.)   { /*핸들 우주선-아스타로이드 충돌*/}     무효 우주선_스페이스(& 다른.)  { /*핸들 우주선-우주선 충돌*/}    일반의:     우주선(): (cid) {}     정적인 무효 초기 케이스();     정적인 컨스턴트 표준::uint32_t cid; // 클래스 ID };  ::Collision Handler Map ::콜리젼 케이스; 컨스턴트 표준::uint32_t 소행성::cid = 유형(소행성).hash_code(); 컨스턴트 표준::uint32_t 우주선::cid = 유형(우주선).hash_code();  무효 소행성: initCases() {     add 핸들러(cid, cid, 충돌 핸들러(&소행성::소행성_소행성));     add 핸들러(cid, 우주선::cid, 충돌 핸들러(&소행성::우주선_스페이스)); }  무효 우주선::initCases() {     add 핸들러(cid, 소행성::cid, 충돌 핸들러(&우주선::소행성_소행성));     add 핸들러(cid, cid, 충돌 핸들러(&우주선::우주선_스페이스)); }  인트 주된() {     소행성::초기 케이스();     우주선::초기 케이스();      소행성  a1, a2;     우주선 s1, s2;      a1.충돌하다(a2);     a1.충돌하다(s1);      s1.충돌하다(s2);     s1.충돌하다(a1); } 

YOMM2 라이브러리는[21] 오픈 멀티소드의 고속 직교 구현을 제공합니다.

오픈 메서드를 선언하기 위한 구문은 네이티브 C++ 구현 제안에서 영감을 얻었습니다.라이브러리에서는 사용자가 가상 인수로 사용되는 모든 클래스(및 하위 클래스)를 등록해야 하지만 기존 코드를 수정할 필요는 없습니다.메서드는 일반적인 인라인 C++ 함수로 구현되며 오버로드되어 포인터로 전달할 수 있습니다.가상 인수 수에는 제한이 없으며, 임의로 비가상 인수와 혼합할 수 있습니다.

라이브러리는 메모리 사용량을 줄이면서 메서드 호출을 일정 시간 내에 구현하기 위해 기술(압축 디스패치 테이블, 무충돌 정수 해시 테이블)의 조합을 사용합니다.최신 최적화 컴파일러가 사용되고 있는 경우, 1개의 가상 인수를 사용하여 콜을 오픈 메서드로 디스패치하는 것은 일반 가상 멤버 함수를 호출하는 것보다 15~30%밖에 걸리지 않습니다.

소행성의 예는 다음과 같이 구현할 수 있습니다.

#실패하다 <yorel/yomm2/hpp> #실패하다 <메모리>  학급  {   일반의:     가상 ~() {} };  학급 소행성 : 일반의  { };  학급 우주선 : 일반의  { };  register_disclossible(, 우주선, 소행성);  declose_disclose(무효, 충돌하다, (가상_< >&>, 가상_< >&>));  defin_define(무효, 충돌하다, (& 왼쪽, & 맞다)) {     // 기본 충돌 처리 }  defin_define(무효, 충돌하다, (소행성& 왼쪽, 소행성& 맞다)) {     // 소행성-아스타로이드 충돌 처리 }  defin_define(무효, 충돌하다, (소행성& 왼쪽, 우주선& 맞다)) {     // 소행성-우주선 충돌 처리 }  defin_define(무효, 충돌하다, (우주선& 왼쪽, 소행성& 맞다)) {     // 우주선-아스테로이드 충돌 처리 }  defin_define(무효, 충돌하다, (우주선& 왼쪽, 우주선& 맞다)) {     // 우주선-우주선 충돌 처리 }  인트 주된() {     할 수 있다::yomm2::update_module();      표준::unique_ptr< >> a1(표준::make_filengths< >소행성>()),         a2(표준::make_filengths< >소행성>());     표준::unique_ptr< >> s1(표준::make_filengths< >우주선>()),         s2(표준::make_filengths< >우주선>());     // 참고: 유형이 부분적으로 지워짐      충돌하다(*a1, *a2); // 소행성-아스타로이드 충돌     충돌하다(*a1, *s1); // 소행성-우주선 충돌     충돌하다(*s1, *a1); // 우주선-아스테로이드 충돌     충돌하다(*s1, *s2); // 우주선 충돌      돌아가다 0; } 

Strustrup은 C++의 설계와 진화에서 멀티메토드의 개념을 마음에 들어 C++에서의 구현을 검토했지만 효율적인 구현 샘플(가상함수에 필적하는 것)을 찾을 수 없었고 가능한 유형의 모호성 문제를 해결할 수 없었다고 주장합니다.그 후, 이 기능을 갖추는 것은 좋은 이지만, 위의 C/C++의 예에서 설명한 대로 더블 디스패치 또는 타입 베이스의 룩업 테이블을 사용해 대략적으로 실장할 수 있기 때문에, 장래의 언어 [22]리비전에서는 우선순위가 낮은 기능입니다.

D

2021년 현재 다른 많은 객체 지향 프로그래밍 언어들과 마찬가지로 D는 기본적으로 단일 디스패치만 지원합니다.단, D에서는 라이브러리 함수로서 오픈 멀티소드를 에뮬레이트 할 수 있습니다.openmethods[23] 라이브러리가 그 예입니다.

// 선언 매트릭스 플러스(가상!매트릭스, 가상!매트릭스);  // 2개의 DenseMatrix 개체에 대한 재정의 @parames(@parames) 매트릭스 _더하기(Dense Matrix(밀도 매트릭스) a, Dense Matrix(밀도 매트릭스) b) {   컨스턴트 인트 nr = a.;   컨스턴트 인트 nc = a.;   주장하다(a.nr == b.nr);   주장하다(a.nc == b.nc);   자동 결과 = 신규 Dense Matrix(밀도 매트릭스);   결과.nr = nr;   결과.nc = nc;   결과.소자.길이 = a.소자.길이;   결과.소자[] = a.소자[] + b.소자[];   돌아가다 결과; }  // 두 개의 대각선 매트릭스 개체에 대한 재정의 @parames(@parames) 매트릭스 _더하기(대각선 매트릭스 a, 대각선 매트릭스 b) {   주장하다(a. == b.);   이중으로 하다[] ;   .길이 = a.소자.길이;   [] = a.소자[] + b.소자[];   돌아가다 신규 대각선 매트릭스(); } 

자바

Java 등 단일 디스패치만을 사용하는 언어에서는 여러 디스패치를 여러 레벨의 단일 디스패치로 에뮬레이트할 수 있습니다.

인터페이스 충돌 가능 {     무효 충돌하다(최종 충돌 가능 다른.);      /* 이러한 메서드에는 메서드의 오버로드가 없는 언어로 다른 이름이 필요합니다.*/     무효 충돌하다(최종 소행성 소행성);     무효 충돌하다(최종 우주선 우주선); }  학급 소행성 용구 충돌 가능 {     일반의 무효 충돌하다(최종 충돌 가능 다른.) {         // 콜 충돌다른 오브젝트에 대해서요.         다른..충돌하다(이것.);    }      일반의 무효 충돌하다(최종 소행성 소행성) {         // 소행성-아스타로이드 충돌을 처리합니다.     }      일반의 무효 충돌하다(최종 우주선 우주선) {         // 소행성과 우주선의 충돌을 처리합니다.     } }  학급 우주선 용구 충돌 가능 {     일반의 무효 충돌하다(최종 충돌 가능 다른.) {         // 콜 충돌다른 오브젝트에 대해서요.         다른..충돌하다(이것.);     }      일반의 무효 충돌하다(최종 소행성 소행성) {         // 우주선-아스테로이드 충돌을 처리합니다.     }      일반의 무효 충돌하다(최종 우주선 우주선) {         // 우주선과 우주선의 충돌을 처리합니다.     } } 

실행 시간instanceof한쪽 또는 양쪽 레벨의 체크도 사용할 수 있습니다.

프로그래밍 언어 지원

주요 패러다임

일반적인 멀티모드 지원

내선 번호 경유

「 」를 참조해 주세요.

레퍼런스

  1. ^ Ranka, Sanjay; Banerjee, Arunava; Biswas, Kanad Kishore; Dua, Sumeet; Mishra, Prabhat; Moona, Rajat (2010-07-26). Contemporary Computing: Second International Conference, IC3 2010, Noida, India, August 9–11, 2010. Proceedings. Springer. ISBN 9783642148248.
  2. ^ a b c d e f g h i j k Muschevici, Radu; Potanin, Alex; Tempero, Ewan; Noble, James (2008). Multiple dispatch in practice. Proceedings of the 23rd ACM SIGPLAN Conference on Object-oriented Programming Systems Languages and Applications. OOPSLA '08. Nashville, TN, USA: ACM. pp. 563–582. doi:10.1145/1449764.1449808. ISBN 9781605582153. S2CID 7605233.
  3. ^ a b c d e Bezanson, Jeff; Edelman, Alan; Karpinski, Stefan; Shah, Viral B. (7 February 2017). "Julia: A fresh approach to numerical computing". SIAM Review. 59 (1): 65–98. arXiv:1411.1607. doi:10.1137/141000671. S2CID 13026838.
  4. ^ Castagna, Giuseppe; Ghelli, Giorgio & Longo, Giuseppe (1995). "A calculus for overloaded functions with subtyping". Information and Computation. 117 (1): 115–135. doi:10.1006/inco.1995.1033. Retrieved 2013-04-19.
  5. ^ Castagna, Giuseppe (1996). Object-Oriented Programming: A Unified Foundation. Progress in Theoretical Computer Science. Birkhäuser. p. 384. ISBN 978-0-8176-3905-1.
  6. ^ Castagna, Giuseppe (1995). "Covariance and contravariance: conflict without a cause". ACM Transactions on Programming Languages and Systems. 17 (3): 431–447. CiteSeerX 10.1.1.115.5992. doi:10.1145/203095.203096. S2CID 15402223.
  7. ^ Bruce, Kim; Cardelli, Luca; Castagna, Giuseppe; Leavens, Gary T.; Pierce, Benjamin (1995). "On binary methods". Theory and Practice of Object Systems. 1 (3): 221–242. doi:10.1002/j.1096-9942.1995.tb00019.x. Retrieved 2013-04-19.
  8. ^ "Using type dynamic (C# Programming Guide)". Retrieved 2020-05-14.
  9. ^ "Basic concepts". Retrieved 2020-05-14.
  10. ^ "Dynamic .NET - Understanding the Dynamic Keyword in C# 4". Retrieved 2020-05-14.
  11. ^ Groovy - 다중 방법
  12. ^ @arrows/multimethod Maciej Cdederek에 의한 설정 가능한 디스패치 해결로 JavaScript/TypeScript에서의 복수 디스패치.
  13. ^ Coady, Aric, multimethod: Multiple argument dispatching., retrieved 2021-01-28
  14. ^ multimethods.py 2005-03-09년 Wayback Machine, Multiple dispatch in Python (David Mertz 등 구성 가능한 디스패치 해결 가능)아카이브(archive)
  15. ^ "Five-minute Multimethods in Python".
  16. ^ "PEAK-Rules 0.5a1.dev". Python Package Index. Retrieved 21 March 2014.
  17. ^ "PyProtocols". Python Enterprise Application Kit. Retrieved 26 April 2019.
  18. ^ "Reg". Read the docs. Retrieved 26 April 2019.
  19. ^ "C Object System: A framework that brings C to the level of other high level programming languages and beyond: CObjectSystem/COS". 2019-02-19.
  20. ^ "Report on language support for Multi-Methods and Open-Methods for C ++" (PDF). 2007-03-11. Multiple dispatch – the selection of a function to be invoked based on the dynamic type of two or more arguments – is a solution to several classical problems in object-oriented programming.{{cite web}}: CS1 maint :url-status (링크)
  21. ^ yomm2, 고속 직교 오픈 멀티메서드 for C++ by Jean-Louis Leroy.
  22. ^ Stroustrup, Bjarne (1994). "Section 13.8". The Design and Evolution of C++. Indianapolis, IN, U.S.A: Addison Wesley. Bibcode:1994dec..book.....S. ISBN 978-0-201-54330-8.
  23. ^ Open Multiple Methods for D by Jean-Louis Leroy.
  24. ^ "Methods". The Julia Manual. Julialang. Archived from the original on 17 July 2016. Retrieved 11 May 2014.
  25. ^ "Multimethods in C# 4.0 With 'Dynamic'". Retrieved 2009-08-20.
  26. ^ "Cecil Language". Retrieved 2008-04-13.
  27. ^ "Multimethods in Clojure". Retrieved 2008-09-04.
  28. ^ Steele, Guy L. (1990). "28". Common LISP: The Language. Bedford, MA, U.S.A: Digital Press. ISBN 978-1-55558-041-4.
  29. ^ "Background and Goals". Retrieved 2008-04-13.
  30. ^ "Elixir Lang Getting Started Modules and functions". Retrieved 2017-11-10.
  31. ^ "The Fortress Language Specification, Version 1.0" (PDF). Archived from the original (PDF) on 2013-01-20. Retrieved 2010-04-23.
  32. ^ "Multimethods in Groovy". Retrieved 2008-04-13.
  33. ^ "Methods – LassoGuide 9.2". Retrieved 2014-11-11.
  34. ^ "Visitor Pattern Versus Multimethods". Retrieved 2008-04-13.
  35. ^ "Nim Manual: Multi-methods". Retrieved 2022-05-03.
  36. ^ "Perl 6 FAQ". Retrieved 2008-04-13.
  37. ^ "How S4 Methods Work" (PDF). Retrieved 2008-04-13.
  38. ^ "Multiple Dispatch in Seed7". Retrieved 2011-04-23.
  39. ^ "TADS 3 System Manual". Retrieved 2012-03-19.
  40. ^ "VB.Net Multiple Dispatch". Retrieved 2020-03-31.
  41. ^ "New Features in C#4.0 and VB.Net 10.0". Retrieved 2020-03-31.
  42. ^ "Notes for Programming Language Experts". Retrieved 2016-08-21.
  43. ^ "Multiple dispatch".

외부 링크