다중 상속
Multiple inheritance다중 상속은 개체 또는 클래스가 둘 이상의 상위 개체 또는 상위 클래스에서 기능을 상속할 수 있는 일부 개체 지향 컴퓨터 프로그래밍 언어의 기능입니다.이는 개체 또는 클래스가 하나의 특정 개체 또는 클래스에서만 상속할 수 있는 단일 상속과는 다릅니다.
다중 상속은 여러 [1][2]부모 클래스가 해당 기능을 구현하는 경우 특정 기능이 어느 부모 클래스에서 상속되는지가 모호할 수 있는 "다이아몬드 문제"와 같은 상황에서 복잡성과 모호성이 증가한다고 지적하면서 오랫동안 논란이 되어 왔습니다.이 문제는 가상 [3]상속을 사용하는 등 다양한 방법으로 해결할 수 있습니다.이 모호성에 대처하기 위해 혼합 및 특성 등 상속을 기반으로 하지 않는 대체 객체 구성 방법도 제안되었다.
세부 사항
객체 지향 프로그래밍(OOP)에서 상속은 하나의 클래스(자녀 클래스)가 부모 클래스를 하위 클래스하는 두 클래스 간의 관계를 나타냅니다.자녀는 부모의 메서드와 속성을 상속하므로 공유 기능을 사용할 수 있습니다.예를 들어 먹는 기능, 재생산 기능 등의 가변 클래스 포유류를 만든 다음 명시적으로 프로그램하지 않고도 이러한 기능을 상속하는 아이 클래스 Cat을 정의하고 마우스 추적과 같은 새로운 기능을 추가할 수 있습니다.
다중 상속을 통해 프로그래머는 Cat이 카툰 캐릭터, 애완동물 및 포유동물에서 상속하고 이러한 모든 클래스 내에서 기능에 액세스할 수 있도록 하는 등 여러 개의 완전 직교 계층을 동시에 사용할 수 있습니다.
실장
다중 상속을 지원하는 언어는 다음과 같습니다.C++, Common Lisp(Common Lisp Object System(CLOS) 경유), EuLisp(EuLisp Object System TELOS 경유), Curl, Dylan, Eiffel, Logtalk, Object REXX, Scala(믹스인 클래스 사용 경유), OCaml, Perl, Pyl, Python, Python, Python
IBM SOM(System Object Model) 런타임은 다중 상속을 지원하며, SOM을 대상으로 하는 프로그래밍 언어는 여러 기반에서 상속된 새로운 SOM 클래스를 구현할 수 있습니다.
2003년 개정판 이후 Swift, Java, Fortran, Ruby와 같은 일부 객체 지향 언어는 단일 상속을 구현하지만 프로토콜 또는 인터페이스는 진정한 다중 상속의 일부 기능을 제공합니다.
PHP는 특성 클래스를 사용하여 특정 메서드 구현을 상속합니다.Ruby는 모듈을 사용하여 여러 메서드를 상속합니다.
다이아몬드 문제
'다이아몬드 문제'(Deady Diamond of [6]Death라고도 함)는 클래스 B와 C가 A에서 상속되고 클래스 D가 B와 C에서 상속될 때 발생하는 모호성입니다.A에 B와 C가 오버라이드한 메서드가 있고 D가 오버라이드하지 않는 경우 D는 B와 C 중 어느 버전의 메서드를 상속받습니까?
예를 들어 GUI 소프트웨어 개발의 경우 클래스는Button
양쪽 클래스에서 상속할 수 있다Rectangle
(외관용) 및Clickable
(기능/입력 처리용) 및 클래스Rectangle
그리고.Clickable
둘 다 로부터 물려받은Object
수업. 이제 만약equals
메서드가 호출됩니다.Button
오브젝트에는 이러한 방법이 없습니다.Button
클래스는 오버라이드되어 있습니다.equals
에 있어서의 방법.Rectangle
또는Clickable
(또는 둘 다) 최종적으로 어떤 메서드를 호출해야 합니까?
이러한 상황에서 클래스 상속 다이어그램의 모양 때문에 "다이아몬드 문제"라고 불립니다.이 경우 클래스 A가 맨 위에 있고 그 아래에 B와 C가 따로 있으며, D는 맨 아래에서 두 개의 클래스를 결합하여 다이아몬드 모양을 형성합니다.
경감
언어에는 이러한 반복적인 유전의 문제를 다루는 다른 방법이 있습니다.
- 디폴트로는 C++는 각 상속 경로를 개별적으로 따릅니다.
D
오브젝트는 실제로는 2개의 독립된 것을 포함합니다.A
오브젝트 및 용도A
님의 멤버는 적절한 자격을 갖추고 있어야 합니다.에서의 상속이A
로.B
로부터 물려받은 유산A
로.C
둘 다 "라고 표시되어 있습니다.virtual
(예를 들어,class B : virtual public A
" ), C++는 1개만 작성하기 위해 특별한 주의를 기울입니다.A
오브젝트 및 용도A
의 멤버는 정상적으로 동작합니다.가상 상속과 비가상 상속이 혼재하는 경우 단일 가상이 있습니다.A
, 및 비가상화A
가상 상속 경로별로A
. C++ 에서는, 사용하는 기능이 어느 부모 클래스에서 기동되는지를 명시적으로 기술할 필요가 있습니다.Worker::Human.Age
. C++는 사용할 슈퍼클래스를 선별할 방법이 없기 때문에 명시적인 반복 상속을 지원하지 않습니다(즉, 클래스가 단일 파생 목록에 두 번 이상 표시됨 [class Dog: public Animal, Animal]).또한 C++에서는 가상 상속 메커니즘(즉, 가상 상속 메커니즘)을 통해 여러 클래스의 단일 인스턴스를 만들 수 있습니다.Worker::Human
그리고.Musician::Human
는 같은 오브젝트를 참조합니다). - 일반적인 LispCLos는 합리적인 기본 동작과 이를 덮어쓰는 기능을 모두 제공하려고 합니다.디폴트로는 간단히 말하면 메서드는 다음과 같이 정렬되어 있습니다.
D,B,C,A
클래스 정의에서 B가 C보다 앞에 쓰여 있는 경우.가장 구체적인 인수 클래스를 가진 메서드가 선택됩니다(D>(B,C)>A). 다음으로 서브 클래스 정의에서 부모 클래스가 명명된 순서(B>C).그러나 프로그래머는 특정 메서드 해결 순서를 지정하거나 메서드를 결합하기 위한 규칙을 기술함으로써 이를 덮어쓸 수 있다.이를 메서드 조합이라고 하며 완전히 제어할 수 있습니다.MOP(metaobject protocol)는 시스템의 안정성에 영향을 주지 않고 상속, 다이내믹디스패치, 클래스 인스턴스화 및 기타 내부 메커니즘을 변경할 수 있는 수단도 제공합니다. - 컬을 사용하면 공유로 명시적으로 표시된 클래스만 반복적으로 상속할 수 있습니다.공유 클래스는 클래스의 각 일반 생성자에 대해 보조 생성자를 정의해야 합니다.일반 컨스트럭터는 공유 클래스의 상태가 서브 클래스 컨스트럭터를 통해 처음 초기화되었을 때 호출되며 다른 모든 서브 클래스에 대해 세컨더리 컨스트럭터가 호출됩니다.
- 에펠에서는 조상들의 특징이 선택과 이름 변경 지시로 명시적으로 선택됩니다.이를 통해 기본 클래스의 기능을 하위 클래스 간에 공유하거나 하위 클래스 각각에 기본 클래스의 개별 복사본을 제공할 수 있습니다.에펠에서는 상위 클래스에서 상속된 피쳐를 명시적으로 결합하거나 분리할 수 있습니다.이름과 구현이 동일한 경우 에펠은 자동으로 기능을 결합합니다.클래스 작성자는 상속된 기능의 이름을 변경하여 이들을 분리할 수 있습니다.Effel 개발에서 다중 상속은 빈번하게 발생합니다. 예를 들어 널리 사용되는 데이터 구조 및 알고리즘의 EffelBase 라이브러리에서 효과적인 클래스 대부분은 [7]두 명 이상의 부모를 두고 있습니다.
- Go는 컴파일 시 다이아몬드 문제를 방지합니다.구조물이
D
2개의 구조를 짜넣다B
그리고.C
둘 다 방법이 있다.F()
따라서 인터페이스를 만족시킵니다.A
컴파일러는 다음과 같은 경우 "compiler selector"에 대해 불만을 제기합니다.D.F()
호출되거나 의 인스턴스가D
유형 변수에 할당되어 있습니다.A
.B
그리고.C
의 메서드는 명시적으로 호출할 수 있습니다.D.B.F()
또는D.C.F()
. - Java 8에서는 인터페이스에 디폴트 방식이 도입되어 있습니다.한다면
A,B,C
인터페이스입니다.B,C
각각은 추상적인 방법에 다른 구현을 제공할 수 있다A
다이아몬드 문제의 원인이 되고 있습니다.어느 클래스든D
는 메서드(본문에서는 단순히 콜을 슈퍼 실장 중 하나로 전송할 수 있음)를 재실장해야 합니다.그렇지 않으면 애매모호성은 [8]컴파일오류로 거부됩니다.Java 8 이전 Java는 다중 상속을 지원하지 않고 인터페이스 기본 메서드를 사용할 수 없었기 때문에 Diamond 문제의 위험이 없었습니다. - 버전 1.2의 JavaFX 스크립트는 mixin을 사용하여 여러 상속을 허용합니다.충돌 시 컴파일러는 모호한 변수나 함수를 직접 사용하는 것을 금지합니다.각 상속된 멤버는 대상 믹스인에 오브젝트를 캐스팅하여 액세스할 수 있습니다.
(individual as Person).printInfo();
. - Kotlin은 인터페이스를 여러 번 상속할 수 있지만 Diamond 문제 시나리오에서는 자식 클래스가 상속 경합을 일으키는 메서드를 덮어쓰고 사용할 부모 클래스 구현을 지정해야 합니다.예
super<ChosenParentInterface>.someMethod()
- Logtalk는 인터페이스와 구현의 양쪽 멀티 상속을 지원하므로 이름 변경과 기본 충돌 해결 메커니즘에 의해 마스킹되는 메서드에 대한 액세스를 모두 제공하는 메서드에일리어스 선언이 가능합니다.
- OCaml에서 부모 클래스는 클래스 정의 본문에 개별적으로 지정됩니다.메서드(및 속성)는 동일한 순서로 상속되며 새로 상속된 각 메서드는 기존 메서드를 덮어씁니다.OCaml은 클래스 상속 목록의 마지막 일치 정의를 선택하여 모호성 하에서 사용할 메서드 구현을 해결합니다.기본 동작을 덮어쓰려면 원하는 클래스 정의를 사용하여 메서드콜을 한정하기만 하면 됩니다.
- Perl은 상속할 클래스 목록을 순서 목록으로 사용합니다.컴파일러는 슈퍼클래스 목록의 깊이 우선 검색 또는 클래스 계층의 C3 선형화를 사용하여 찾은 첫 번째 방법을 사용합니다.다양한 확장이 대체 클래스 구성 체계를 제공합니다.상속 순서는 클래스 의미론에 영향을 미칩니다.상기의 애매함 속에서,
B
그리고 수업 전에 그것의 조상들을 확인할 것이다.C
그리고 그 조상들, 그래서 그 방법은A
통해 유전될 것이다B
Io 및 Picolisp와 공유됩니다.Perl에서는 이 동작을 덮어쓸 수 있습니다.mro
또는 C3 선형화 또는 기타 [9]알고리즘을 사용하는 다른 모듈. - Python은 Perl과 구조가 동일하지만 Perl과는 달리 언어 구문에 포함되어 있습니다.상속 순서는 클래스 의미론에 영향을 미칩니다.Python은 새로운 스타일의 클래스를 도입했을 때 이 문제에 대처해야 했습니다.이러한 클래스에는 모두 공통의 조상이 있습니다.
object
Python은 C3 선형화(또는 MRO) 알고리즘을 사용하여 클래스 목록을 만듭니다.이 알고리즘에서는 부모보다 하위 클래스에서 하위 클래스가 상속되는 경우 하위 클래스가 기본 클래스의 태플에서 지정된 순서대로 유지됩니다(단, 이 경우 상속 그래프의 상위 클래스가 하위[10] 클래스보다 우선할 수 있습니다).따라서 방법 해결 순서는 다음과 같습니다.D
,B
,C
,A
를 클릭합니다.[11] - 루비 클래스는 정확히 한 개의 부모를 가지지만 여러 모듈로부터 상속될 수도 있습니다. 루비 클래스 정의가 실행되며 메서드의 (재) 정의는 실행 시 이전에 존재했던 정의를 가립니다.런타임 메타프로그래밍이 없는 경우, 이것은 가장 오른쪽의 깊이 우선 해상도와 거의 동일한 의미를 가집니다.
- Scala를 사용하면 특성을 여러 인스턴스화할 수 있으며 클래스 계층과 특성 계층 간의 구별을 추가하여 여러 상속이 가능합니다.클래스는 단일 클래스에서만 상속할 수 있지만 원하는 만큼의 특성을 혼합할 수 있습니다.Scala는 결과 목록에서 각 모듈의 마지막 항목을 제외한 모든 항목을 제거하기 전에 확장 '트레이트'의 오른쪽 첫 번째 깊이 우선 검색을 사용하여 메서드 이름을 해결합니다.따라서 해결 순서는 다음과 같습니다.
D
,C
,A
,B
,A
], 즉 []로 감소합니다.D
,C
,B
,A
]. - TCL은 여러 부모 클래스를 허용합니다.클래스 선언의 지정 순서는 C3 선형화 알고리즘을 [12]사용하는 멤버의 이름 해결에 영향을 줍니다.
클래스가 하나의 기본 클래스에서 파생될 수 있는 단일 상속만 허용하는 언어에는 다이아몬드 문제가 없습니다.그 이유는 이러한 언어들이 메서드의 반복이나 배치에 관계없이 상속 체인의 모든 수준에서 어떤 메서드의 구현을 최대 1개만 가지고 있기 때문이다.일반적으로 이러한 언어를 사용하면 클래스가 Java에서 인터페이스라고 하는 여러 프로토콜을 구현할 수 있습니다.이러한 프로토콜은 방법을 정의하지만 구체적인 구현을 제공하지는 않습니다.이 전략은 ActionScript, C#, D, Java, Nemerle, Object Pascal, Objective-C, Smalltalk, Swift 및 [13]PHP에서 사용되고 있습니다.이러한 모든 언어를 통해 클래스에서 여러 프로토콜을 구현할 수 있습니다.
또한 Ada, C#, Java, Object Pascal, Objective-C, Swift 및 PHP는 인터페이스의 다중 상속을 허용합니다(Objective-C 및 Swift에서는 프로토콜이라고 함).인터페이스는 동작을 실장하지 않고 메서드시그니처를 지정하는 추상 베이스 클래스와 같습니다("Java 버전7까지의 인터페이스 등 순수" 인터페이스에서는 인터페이스 내의 구현 또는 인스턴스 데이터는 허용되지 않습니다).다만, 복수의 인터페이스가 같은 메서드시그니처를 선언하고 있는 경우에서도, 그 메서드가 상속 체인내의 임의의 장소에 실장(정의)되면, 그 위의 체인내의(슈퍼 클래스내의) 그 메서드의 실장은 덮어씁니다.따라서 상속 사슬의 특정 수준에서, 어떤 방법의 구현도 최대 1개일 수 있다.따라서 단일 상속 방식의 구현에서는 인터페이스의 다중 상속이 있더라도 다이아몬드 문제가 발생하지 않습니다.Java 8 및 C#8에서 인터페이스에 기본 구현이 도입되어도 Diamond 문제가 발생할 수 있지만 이는 컴파일 시 오류로밖에 표시되지 않습니다.
「 」를 참조해 주세요.
레퍼런스
- ^ Cargill, T. A. (Winter 1991). "Controversy: The Case Against Multiple Inheritance in C++". Computing Systems. 4 (1): 69–82.
- ^ Waldo, Jim (Spring 1991). "Controversy: The Case For Multiple Inheritance in C++". Computing Systems. 4 (2): 157–171.
- ^ Schärli, Nathanael; Ducasse, Stéphane; Nierstrasz, Oscar; Black, Andrew. "Traits: Composable Units of Behavior" (PDF). Web.cecs.pdx.edu. Retrieved 2016-10-21.
- ^ "incr Tcl". blog.tcl.tk. Retrieved 2020-04-14.
- ^ "Introduction to the Tcl Programming Language". www2.lib.uchicago.edu. Retrieved 2020-04-14.
- ^ Martin, Robert C. (1997-03-09). "Java and C++: A critical comparison" (PDF). Objectmentor.com. Archived from the original (PDF) on 2005-10-24. Retrieved 2016-10-21.
- ^ "Standard ECMA-367". Ecma-international.org. Retrieved 2016-10-21.
- ^ "State of the Lambda". Cr.openjdk.java.net. Retrieved 2016-10-21.
- ^ "perlobj". perldoc.perl.org. Retrieved 2016-10-21.
- ^ Abstract. "The Python 2.3 Method Resolution Order". Python.org. Retrieved 2016-10-21.
- ^ "Unifying types and classes in Python 2.2". Python.org. Retrieved 2016-10-21.
- ^ "Manpage of class". Tcl.tk. 1999-11-16. Retrieved 2016-10-21.
- ^ "Object Interfaces - Manual". PHP.net. 2007-07-04. Retrieved 2016-10-21.
추가 정보
- Stroustrup, Bjarne(1999년).C++의 다중 상속.1987년 봄 유럽 유닉스 사용자 그룹 회의 진행
- 오브젝트 지향 소프트웨어 구축, 제2판, 프렌티스 홀, 베르트랑 마이어, 1997, ISBN 0-13-629155-4
- Eddy Truyen; Wouter Joosen; Bo Nørregaard; Pierre Verbaeten (2004). "A Generalization and Solution to the Common Ancestor Dilemma Problem in Delegation-Based Object Systems" (PDF). Proceedings of the 2004 Dynamic Aspects Workshop (103–119).
- Ira R. Forman; Scott Danforth (1999). Putting Metaclasses to Work. ISBN 0-201-43305-2.