"다중상속"의 두 판 사이의 차이
잔글 |
잔글 |
||
(사용자 2명의 중간 판 18개는 보이지 않습니다) | |||
1번째 줄: | 1번째 줄: | ||
− | '''다중상속'''(multiple inheritance)은 [[객체 지향 프로그래밍]]에서 한 [[클래스]]가 한 번에 두 개 이상의 클래스를 | + | '''다중상속'''<!--다중 상속-->(multiple inheritance)은 [[객체 지향 프로그래밍]]에서 한 [[클래스]]가 한 번에 두 개 이상의 클래스를 [[상속 (프로그래밍)|상속]]받는 경우를 말한다. 다중상속을 받은 [[클래스]]의 경우 두 개 이상의 부모 클래스를 가지게 된다. |
− | == | + | == 개요 == |
− | 다중상속( | + | 다중상속(multiple inheritance)이란 [[객체 지향 프로그래밍]]의 특징 중 하나이며, 어떤 클래스가 하나 이상의 상위 클래스로부터 여러 가지 행동이나 특징을 [[상속 (프로그래밍)|상속]]받을 수 있는 것을 말한다. 다중상속을 허용하면 여러 클래스로부터 상속 받을 수 있기 때문에 복합적인 기능을 가진 클래스를 쉽게 작성할 수 있지만 프로그래밍을 복잡하게 만들 수 있기 때문에 실용성이 떨어진다.<ref name="자료1"> 힘껏 날아 오르자!, 〈[http://blog.daum.net/dsmcj/37 다중상속과 단일상속의 장단점]〉, 《개인블로그》, 2009-03-11</ref> |
− | == | + | == 특징 == |
+ | 다중 상속을 지원하게 되면 하나 이상의 상위 클래스로부터 여러가지 특징을 상속 받을 수 있다. 하지만 이러한 장점 때문에 상속 구조에 문제가 생겨 오히려 프로그래밍을 복잡하게 만들 수 있다는 특징을 가지고 있다. | ||
+ | |||
+ | ===C++=== | ||
+ | 단일 상속과는 다르게 두 개 이상의 [[클래스]]를 하나가 동시에 상속받는 것으로 클래스를 선언할 때 클래스명 옆 : [[연산자]] 뒤에 여러 개의 클래스를 콤마(,)로 나열한다. | ||
+ | class A{ | ||
+ | public: | ||
+ | void sampleA(){ | ||
+ | cout<<"A : example"<<endl; | ||
+ | } | ||
+ | }; | ||
+ | |||
+ | class B{ | ||
+ | public: | ||
+ | void sampleB(){ | ||
+ | cout<<"B : example"<<endl; | ||
+ | } | ||
+ | }; | ||
+ | |||
+ | class C : public A, public B{ | ||
+ | public: | ||
+ | void sampleC(){ | ||
+ | sampleA(); | ||
+ | sampleB(); | ||
+ | } | ||
+ | }; | ||
+ | |||
+ | int main(){ | ||
+ | C exampleC; | ||
+ | exampleC.sampleC(); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | |||
+ | 클래스 C에서 A와 B 클래스를 [[상속 (프로그래밍)|상속]] 받았다. 이 때 두 개 이상의 클래스를 동시에 상속받은 C는 다중 상속을 받았다고 하며 클래스A와 클래스B가 가지고 있는 속성들을 사용할 수 있다. | ||
+ | |||
+ | 이 때 클래스A의 sampleA 함수와 클래스B의 sampleB 함수가 sample이라는 함수로 정의되어 있을 때 클래스 C에서 함수를 사용할 때 아래와 같이 작성이 되어 모호성이 발생한다.<ref name="자료2"> Pac, 〈[https://pacs.tistory.com/entry/C-%EC%83%81%EC%86%8D%EC%9D%98-%EB%A7%88%EC%A7%80%EB%A7%89-%EB%8B%A4%EC%A4%91-%EC%83%81%EC%86%8DMultiple-Inheritance 상속의 마지막, 다중 상속(Multiple Inheritance)]〉, 《개인블로그》, 2010-09-17</ref> | ||
+ | |||
+ | class C : public A, public B{ | ||
+ | public: | ||
+ | void sampleC(){ | ||
+ | sample(); //A클래스의 sample | ||
+ | sample(); //B클래스의 sample | ||
+ | } | ||
+ | }; | ||
+ | |||
+ | 위와 같은 모호성 때문에 생기는 문제를 다이아몬드 문제라고 하는데 이는 구조가 다이아몬드 형태를 띄우고 있어 붙여진 이름이다. | ||
+ | |||
+ | ===다이아몬드 문제=== | ||
+ | |||
+ | [[파일:다중상속문제.PNG | 500픽셀]] | ||
+ | |||
+ | 위의 클래스 다이어그램과 같은 [[상속 (프로그래밍)|상속]] 구조에서 발생되는 문제가 다이아몬드 문제이다. Grand라는 클래스에서 example이라는 [[메소드]]를 가질 때 상속을 받은 ParentsA와 ParentsB에서는 example이라는 메소드를 [[오버라이딩]]한다. 이 때 son에서 example이라는 메소드를 불러올 때 어떤 부모의 메소드를 불러와야 하는지 모호해져서 충돌이 생기게 된다. 이를 다이아몬드 문제라고 하는데 [[자바]]에서는 이러한 문제를 사전에 방지하기 위해서 다중 상속을 지원하지 않는다. | ||
+ | |||
+ | ===자바=== | ||
+ | [[자바]]는 다이아몬드 문제를 방지하기 위해 다중 상속을 지원하지 않는다. 하지만 이런 문제가 있음에도 불구하고 [[인터페이스]]를 통해 다중상속의 기능을 사용할 수 있다. | ||
+ | 인터페이스를 이용한 다중 상속은 실제로 구현했을 때 아무런 문제를 발생시키지 않는다. 그 이유는 인터페이스의 기능 때문이다. 인터페이스는 [[메소드]]의 기능에 대해 선언만 해두기 때문에 다이아몬드 상속이 되더라도 충돌할 여지가 없다.<ref name="자료3"> 사용자 siyoon210, 〈[https://siyoon210.tistory.com/125 자바는 왜 다중상속을 지원하지 않을까? (다이아몬드 문제)]〉, 《개인블로그》, 2019-02-24</ref> | ||
+ | |||
+ | interface Grand { | ||
+ | void example(); | ||
+ | } | ||
+ | |||
+ | interface ParentsA extends Grand { | ||
+ | @Override | ||
+ | void example(); | ||
+ | } | ||
+ | |||
+ | interface ParentsB extends Grand { | ||
+ | @Override | ||
+ | void example(); | ||
+ | } | ||
+ | |||
+ | interface son extends ParentsA, ParentsB { | ||
+ | @Override | ||
+ | void example(); | ||
+ | } | ||
+ | |||
+ | 위와 같이 [[인터페이스]]에 선언을 하여 extends를 활용해 다중 상속이 가능하다. | ||
+ | |||
+ | ===파이썬=== | ||
+ | 파이썬에서 다중 상속을 받기 위해서는 'class 클래스이름(부모클래스이름1, 부모클래스이름2): 코드' 형식을 사용한다. 여러 클래스로부터 상속을 받을 때 괄호 안에 클래스 이름을 콤마(,)로 구분해서 넣는다. | ||
+ | |||
+ | class 클래스이름1: | ||
+ | 코드 | ||
+ | class 클래스이름2: | ||
+ | 코드 | ||
+ | class 클래스이름3(클래스이름1, 클래스이름2): | ||
+ | 코드 | ||
+ | |||
+ | 많은 프로그래밍 언어들이 다이아몬드 문제에 대한 해결책을 제시하고 있는데 파이썬에서는 메서드 탐색 순서를 따른다. 파이썬은 다중 상속을 할 때 상속 클래스 목록 중 왼쪽에서 오른쪽 순서로 메서드를 찾는다. 그러므로 같은 메서드가 있다면 왼쪽에 있는 클래스 내의 메서드를 우선으로 한다. 만약 상속관계가 복잡하게 얽혀있다면 MRO 메서도를 사용해 살펴보는것이 편리하다.<ref name="자료5"> 코딩도장, 〈[https://dojang.io/mod/page/view.php?id=2388 다중 상속 사용하기]〉, 《코딩도장》</ref> | ||
+ | |||
+ | ===C#=== | ||
+ | C#에서 클래스는 여러 클래스를 동시에 상속하는 다중상속이 불가능하다.<ref name="자료6"> 셩님, 〈[https://debuglog.tistory.com/134 인터페이스 다중 상속]〉, 《개인블로그》, 2018-06-18</ref> 하지만 자바와 같이 인터페이스를 활용한 다중 상속은 가능하다. | ||
+ | |||
+ | interface A{ | ||
+ | void sampleA(); | ||
+ | } | ||
+ | |||
+ | interface B{ | ||
+ | void sampleB(); | ||
+ | } | ||
+ | |||
+ | class C : A, B | ||
+ | { | ||
+ | void sampleA(){ | ||
+ | 코드 | ||
+ | } | ||
+ | void sampleB(){ | ||
+ | 코드 | ||
+ | } | ||
+ | } | ||
+ | |||
+ | 위와 같이 인터페이스를 사용하면 다중 상속이 가능하다. 이 때 클래스 하나와 여러 인터페이스를 상속 받는 것 또한 가능하다. 하지만 클래스가 여러개 들어가는 것은 사용할 수 없다. | ||
+ | |||
+ | class A{ | ||
+ | void sampleA(); | ||
+ | } | ||
+ | |||
+ | interface B{ | ||
+ | void sampleB(); | ||
+ | } | ||
+ | |||
+ | class C : A, B | ||
+ | { | ||
+ | void sampleA(){ | ||
+ | 코드 | ||
+ | } | ||
+ | void sampleB(){ | ||
+ | 코드 | ||
+ | } | ||
+ | } | ||
+ | |||
+ | ===문제점=== | ||
+ | 다중 상속의 문제점은 크게 두가지가 있다. 첫 번째 문제는 [[변수]]의 모호함 때문에 구현을 막아놓은 것이다. 각 부모클래스의 똑같은 이름의 [[속성]], [[메소드]]를 가진 상황이 있다고 가정하면 그 변수, 메소드가 어느 부모를 상속하여 받아서 사용되는 지를 그 자체를 이해하지 못하기 때문이다. | ||
+ | 그리고 두 번째 문제로는 상속 기능의 무거움이다. 실무에서 사용할 때 [[객체 지향 프로그래밍]]은 속성이 1개에서 10개로 끝나지 않고 다루는 메소드만 해도 수없이 많다. 이렇게 많은 속성들을 다중으로 상속을 받는다면 프로그램 자체에 큰 부담을 줄 수 있다. | ||
+ | |||
+ | [[C++]]에서는 이름 공간이라는 기능을 이용해서 데이터의 모호함을 구별 할 수 있게 해 두었다. 그리고 [[상속 (프로그래밍)|상속]]의 경우가 아닌 [[메소드]]만 상속을 받아와서 속성 값을 제어할 수 있는 [[인터페이스]]라는 기능을 만들었다. 하지만 인터페이스 기능을 사용하기 위해서는 반드시 메소드의 구현을 해야한다. | ||
+ | |||
+ | 이렇게 문제점을 극복할 수 있는 기능들이 있지만 기업간의 협업과 유지보수에서 코드의 모호함으로 인해 어려움을 격기 때문에 다중 상속을 잘 사용하지 않게 되었다.<ref name="자료4"> 김형수, 〈[https://m.blog.naver.com/PostView.nhn?blogId=there924&logNo=220857891926&proxyReferer=https%3A%2F%2Fwww.google.com%2F 객체지향(6) - 다중상속]〉, 《개인블로그》, 2016-11-10</ref> | ||
{{각주}} | {{각주}} | ||
+ | |||
+ | ==참고자료== | ||
+ | * 힘껏 날아 오르자!, 〈[http://blog.daum.net/dsmcj/37 다중상속과 단일상속의 장단점]〉, 《개인블로그》, 2009-03-11 | ||
+ | * Pac, 〈[https://pacs.tistory.com/entry/C-%EC%83%81%EC%86%8D%EC%9D%98-%EB%A7%88%EC%A7%80%EB%A7%89-%EB%8B%A4%EC%A4%91-%EC%83%81%EC%86%8DMultiple-Inheritance 상속의 마지막, 다중 상속(Multiple Inheritance)]〉, 《개인블로그》, 2010-09-17 | ||
+ | * 사용자 siyoon210, 〈[https://siyoon210.tistory.com/125 자바는 왜 다중상속을 지원하지 않을까? (다이아몬드 문제)]〉, 《개인블로그》, 2019-02-24 | ||
+ | * 김형수, 〈[https://m.blog.naver.com/PostView.nhn?blogId=there924&logNo=220857891926&proxyReferer=https%3A%2F%2Fwww.google.com%2F 객체지향(6) - 다중상속]〉, 《개인블로그》, 2016-11-10 | ||
+ | * 코딩도장, 〈[https://dojang.io/mod/page/view.php?id=2388 다중 상속 사용하기]〉, 《코딩도장》 | ||
+ | * 셩님, 〈[https://debuglog.tistory.com/134 인터페이스 다중 상속]〉, 《개인블로그》, 2018-06-18 | ||
== 같이 보기 == | == 같이 보기 == | ||
* [[객체 지향 프로그래밍]] | * [[객체 지향 프로그래밍]] | ||
* [[클래스]] | * [[클래스]] | ||
− | * [[상속]] | + | * [[상속 (프로그래밍)|상속]] |
+ | * [[메소드]] | ||
+ | * [[오버라이딩]] | ||
+ | * [[자바]] | ||
+ | * [[C++]] | ||
+ | * [[파이썬]] | ||
+ | * [[C#]] | ||
+ | * [[인터페이스]] | ||
− | {{프로그래밍| | + | {{프로그래밍|검토 필요}} |
2022년 1월 31일 (월) 23:35 기준 최신판
다중상속(multiple inheritance)은 객체 지향 프로그래밍에서 한 클래스가 한 번에 두 개 이상의 클래스를 상속받는 경우를 말한다. 다중상속을 받은 클래스의 경우 두 개 이상의 부모 클래스를 가지게 된다.
개요[편집]
다중상속(multiple inheritance)이란 객체 지향 프로그래밍의 특징 중 하나이며, 어떤 클래스가 하나 이상의 상위 클래스로부터 여러 가지 행동이나 특징을 상속받을 수 있는 것을 말한다. 다중상속을 허용하면 여러 클래스로부터 상속 받을 수 있기 때문에 복합적인 기능을 가진 클래스를 쉽게 작성할 수 있지만 프로그래밍을 복잡하게 만들 수 있기 때문에 실용성이 떨어진다.[1]
특징[편집]
다중 상속을 지원하게 되면 하나 이상의 상위 클래스로부터 여러가지 특징을 상속 받을 수 있다. 하지만 이러한 장점 때문에 상속 구조에 문제가 생겨 오히려 프로그래밍을 복잡하게 만들 수 있다는 특징을 가지고 있다.
C++[편집]
단일 상속과는 다르게 두 개 이상의 클래스를 하나가 동시에 상속받는 것으로 클래스를 선언할 때 클래스명 옆 : 연산자 뒤에 여러 개의 클래스를 콤마(,)로 나열한다.
class A{ public: void sampleA(){ cout<<"A : example"<<endl; } }; class B{ public: void sampleB(){ cout<<"B : example"<<endl; } }; class C : public A, public B{ public: void sampleC(){ sampleA(); sampleB(); } }; int main(){ C exampleC; exampleC.sampleC(); return 0; }
클래스 C에서 A와 B 클래스를 상속 받았다. 이 때 두 개 이상의 클래스를 동시에 상속받은 C는 다중 상속을 받았다고 하며 클래스A와 클래스B가 가지고 있는 속성들을 사용할 수 있다.
이 때 클래스A의 sampleA 함수와 클래스B의 sampleB 함수가 sample이라는 함수로 정의되어 있을 때 클래스 C에서 함수를 사용할 때 아래와 같이 작성이 되어 모호성이 발생한다.[2]
class C : public A, public B{ public: void sampleC(){ sample(); //A클래스의 sample sample(); //B클래스의 sample } };
위와 같은 모호성 때문에 생기는 문제를 다이아몬드 문제라고 하는데 이는 구조가 다이아몬드 형태를 띄우고 있어 붙여진 이름이다.
다이아몬드 문제[편집]
위의 클래스 다이어그램과 같은 상속 구조에서 발생되는 문제가 다이아몬드 문제이다. Grand라는 클래스에서 example이라는 메소드를 가질 때 상속을 받은 ParentsA와 ParentsB에서는 example이라는 메소드를 오버라이딩한다. 이 때 son에서 example이라는 메소드를 불러올 때 어떤 부모의 메소드를 불러와야 하는지 모호해져서 충돌이 생기게 된다. 이를 다이아몬드 문제라고 하는데 자바에서는 이러한 문제를 사전에 방지하기 위해서 다중 상속을 지원하지 않는다.
자바[편집]
자바는 다이아몬드 문제를 방지하기 위해 다중 상속을 지원하지 않는다. 하지만 이런 문제가 있음에도 불구하고 인터페이스를 통해 다중상속의 기능을 사용할 수 있다. 인터페이스를 이용한 다중 상속은 실제로 구현했을 때 아무런 문제를 발생시키지 않는다. 그 이유는 인터페이스의 기능 때문이다. 인터페이스는 메소드의 기능에 대해 선언만 해두기 때문에 다이아몬드 상속이 되더라도 충돌할 여지가 없다.[3]
interface Grand { void example(); } interface ParentsA extends Grand { @Override void example(); } interface ParentsB extends Grand { @Override void example(); } interface son extends ParentsA, ParentsB { @Override void example(); }
위와 같이 인터페이스에 선언을 하여 extends를 활용해 다중 상속이 가능하다.
파이썬[편집]
파이썬에서 다중 상속을 받기 위해서는 'class 클래스이름(부모클래스이름1, 부모클래스이름2): 코드' 형식을 사용한다. 여러 클래스로부터 상속을 받을 때 괄호 안에 클래스 이름을 콤마(,)로 구분해서 넣는다.
class 클래스이름1: 코드 class 클래스이름2: 코드 class 클래스이름3(클래스이름1, 클래스이름2): 코드
많은 프로그래밍 언어들이 다이아몬드 문제에 대한 해결책을 제시하고 있는데 파이썬에서는 메서드 탐색 순서를 따른다. 파이썬은 다중 상속을 할 때 상속 클래스 목록 중 왼쪽에서 오른쪽 순서로 메서드를 찾는다. 그러므로 같은 메서드가 있다면 왼쪽에 있는 클래스 내의 메서드를 우선으로 한다. 만약 상속관계가 복잡하게 얽혀있다면 MRO 메서도를 사용해 살펴보는것이 편리하다.[4]
C#[편집]
C#에서 클래스는 여러 클래스를 동시에 상속하는 다중상속이 불가능하다.[5] 하지만 자바와 같이 인터페이스를 활용한 다중 상속은 가능하다.
interface A{ void sampleA(); } interface B{ void sampleB(); }
class C : A, B { void sampleA(){ 코드 } void sampleB(){ 코드 } }
위와 같이 인터페이스를 사용하면 다중 상속이 가능하다. 이 때 클래스 하나와 여러 인터페이스를 상속 받는 것 또한 가능하다. 하지만 클래스가 여러개 들어가는 것은 사용할 수 없다.
class A{ void sampleA(); } interface B{ void sampleB(); }
class C : A, B { void sampleA(){ 코드 } void sampleB(){ 코드 } }
문제점[편집]
다중 상속의 문제점은 크게 두가지가 있다. 첫 번째 문제는 변수의 모호함 때문에 구현을 막아놓은 것이다. 각 부모클래스의 똑같은 이름의 속성, 메소드를 가진 상황이 있다고 가정하면 그 변수, 메소드가 어느 부모를 상속하여 받아서 사용되는 지를 그 자체를 이해하지 못하기 때문이다. 그리고 두 번째 문제로는 상속 기능의 무거움이다. 실무에서 사용할 때 객체 지향 프로그래밍은 속성이 1개에서 10개로 끝나지 않고 다루는 메소드만 해도 수없이 많다. 이렇게 많은 속성들을 다중으로 상속을 받는다면 프로그램 자체에 큰 부담을 줄 수 있다.
C++에서는 이름 공간이라는 기능을 이용해서 데이터의 모호함을 구별 할 수 있게 해 두었다. 그리고 상속의 경우가 아닌 메소드만 상속을 받아와서 속성 값을 제어할 수 있는 인터페이스라는 기능을 만들었다. 하지만 인터페이스 기능을 사용하기 위해서는 반드시 메소드의 구현을 해야한다.
이렇게 문제점을 극복할 수 있는 기능들이 있지만 기업간의 협업과 유지보수에서 코드의 모호함으로 인해 어려움을 격기 때문에 다중 상속을 잘 사용하지 않게 되었다.[6]
각주[편집]
- ↑ 힘껏 날아 오르자!, 〈다중상속과 단일상속의 장단점〉, 《개인블로그》, 2009-03-11
- ↑ Pac, 〈상속의 마지막, 다중 상속(Multiple Inheritance)〉, 《개인블로그》, 2010-09-17
- ↑ 사용자 siyoon210, 〈자바는 왜 다중상속을 지원하지 않을까? (다이아몬드 문제)〉, 《개인블로그》, 2019-02-24
- ↑ 코딩도장, 〈다중 상속 사용하기〉, 《코딩도장》
- ↑ 셩님, 〈인터페이스 다중 상속〉, 《개인블로그》, 2018-06-18
- ↑ 김형수, 〈객체지향(6) - 다중상속〉, 《개인블로그》, 2016-11-10
참고자료[편집]
- 힘껏 날아 오르자!, 〈다중상속과 단일상속의 장단점〉, 《개인블로그》, 2009-03-11
- Pac, 〈상속의 마지막, 다중 상속(Multiple Inheritance)〉, 《개인블로그》, 2010-09-17
- 사용자 siyoon210, 〈자바는 왜 다중상속을 지원하지 않을까? (다이아몬드 문제)〉, 《개인블로그》, 2019-02-24
- 김형수, 〈객체지향(6) - 다중상속〉, 《개인블로그》, 2016-11-10
- 코딩도장, 〈다중 상속 사용하기〉, 《코딩도장》
- 셩님, 〈인터페이스 다중 상속〉, 《개인블로그》, 2018-06-18
같이 보기[편집]