다중 상속이란?
다중 상속(multiple inheritance)은 자식클래스가 하나 이상의 부모클래스로부터 그 특성을 상속받는 것을 말합니다. 다중 상속된 자식클래스는 모든 부모클래스의 데이터멤버 및 멤버함수의 특성을 다 가지게 되므로 부모클래스의 데이터멤버 및 멤버함수를 사용할 수 있습니다.
다중상속의 필요성
객체지향 프로그래밍을 하다보면 많은 경우에 접하게 되는 것이 다중 상속 개념입니다. 다중 상속이야말로 특성 상속의 가장 기본적인 것이라고 할 수 있습니다.
< 다중 상속의 예 >
그림의 예에서 보듯이 서로 독립적인 4개의 클래스(더하기, 빼기, 곱하기, 나누기 클래스)로부터 데이터멤버 및 멤버함수를 상속받은 계산기 클래스가 만들어지게 됩니다.
PHP에서의 다중 상속
PHP에서는 단일상속에 관하여는 별문제없이 그 부모클래스의 특성을 상속받을 수 있습니다. 그러나 복수의 부모클래스의 특성을 상속받을 수는 없습니다. 이러한 다중상속의 문제는 웹사이트 구조가 복잡해 질 수록 절실해지게 되며, 자원(클래스)의 재사용이란 측면에서 볼 때도 꼭 필요한 기능이라고 할 수 있습니다. 이러한 다중상속을 후키라이브러리를 이용하면 손쉽게 구현할 수 있습니다.
다중 상속 정의하기
[code php;gutter:false] /*
파일명 class.더하기.php
부모클래스 더하기 정의
*/

classdefine("
class 더하기Interclass {}
");

class 더하기 extends 더하기Interclass {
.... 이곳에 부모클래스 더하기의 멤버함수 및 데이터멤버를 정의합니다.
}

/*
파일명 class.빼기.php
부모클래스 빼기 정의
*/

classdefine("
class 빼기Interclass {}
");

class 빼기 extends 빼기Interclass {
.... 이곳에 부모클래스 빼기의 멤버함수 및 데이터멤버를 정의합니다.
}

/*
파일명 class.곱하기.php
부모클래스 곱하기 정의
*/

classdefine("
class 곱하기Interclass {}
");

class 곱하기 extends 곱하기Interclass {
.... 이곳에 부모클래스 곱하기의 멤버함수 및 데이터멤버를 정의합니다.
}

/*
파일명 class.나누기.php
부모클래스 나누기 정의
*/

classdefine("
class 나누기Interclass {}
");

class 나누기 extends 나누기Interclass {
.... 이곳에 부모클래스 나누기의 멤버함수 및 데이터멤버를 정의합니다.
}

/*
파일명 class.계산기.php
자식클래스 계산기 정의
*/

classdefine("
class 계산기Interclass extends 더하기, 빼기, 곱하기, 나누기 { }
");

class 계산기 extends 계산기Interclass {
.... 이곳에 자식클래스 계산기의 멤버함수 및 데이터멤버를 정의합니다.
} [/code]
위와 같은 예를 보면 현재클래스 계산기는 부모클래스 더하기, 빼기, 곱하기 및 나누기로부터 다중 상속받도록 되어 있습니다.
classdefine 함수는 클래스 정의 문자열을 해석하면서 클래스 다중 상속을 지원할 수 있도록 상속에 필요한 부모클래스 정의 파일을 인클루드 시킵니다. PHP 스크립트는 클래스 다중 상속을 지원하지 않기 때문에 클래스 정의 문자열을 해석하면서 단일 상속으로 변환시켜 줍니다. 즉, 다중 상속을 단일 상속형태로 변환시켜 주는 역할을 자동적으로 수행합니다.
동일한 조상클래스(ancestor class)를 가진 다중 상속
동일한 부모클래스로부터 서로 다른 길을 통해 상속된 두 개 이상의 파생클래스를 다중 상속할 수 있습니다. 동일한 클래스를 두번 이상 정의하게 되면 PHP는 에러를 발생시킵니다. 이러한 문제를 해결하기 위해 "후키라이브러리"에서는 동일한 부모클래스를 단 한번만 포함하도록 동작합니다. 이는 C++에서 가상클래스(virtual class)를 이용하는 것과 비슷한 기능을 한다고 볼 수 있습니다. 즉, 가상클래스를 이용하는 것은 파생클래스가 동일한 부모클래스를 여러 번 상속했다고 하더라도 하나의 클래스만을 파생클래스에 포함시키도록 하는 것입니다.
< 동일한 조상클래스를 가진 다중 상속의 예 >
[code php;gutter:false] /*
파일명 class.숫자.php
조상클래스 숫자 정의
*/

classdefine("
class 숫자Interclass {}
");

class 숫자 extends 숫자Interclass {
.... 이곳에 조상클래스 숫자의 멤버함수 및 데이터멤버를 정의합니다.
}

/*
파일명 class.더하기.php
부모클래스 더하기 정의
*/

classdefine("
class 더하기Interclass extends 숫자 {}
");

class 더하기 extends 더하기Interclass {
.... 이곳에 부모클래스 더하기의 멤버함수 및 데이터멤버를 정의합니다.
}

/*
파일명 class.빼기.php
부모클래스 빼기 정의
*/

classdefine("
class 빼기Interclass extends 숫자 {}
");

class 빼기 extends 빼기Interclass {
.... 이곳에 부모클래스 빼기의 멤버함수 및 데이터멤버를 정의합니다.
}

/*
파일명 class.곱하기.php
부모클래스 곱하기 정의
*/

classdefine("
class 곱하기Interclass extends 숫자 {}
");

class 곱하기 extends 곱하기Interclass {
.... 이곳에 부모클래스 곱하기의 멤버함수 및 데이터멤버를 정의합니다.
}

/*
파일명 class.나누기.php
부모클래스 나누기 정의
*/

classdefine("
class 나누기Interclass extends 숫자 {}
");

class 나누기 extends 나누기Interclass {
.... 이곳에 부모클래스 나누기의 멤버함수 및 데이터멤버를 정의합니다.
}

/*
파일명 class.계산기.php
자식클래스 계산기 정의
*/

classdefine("
class 계산기Interclass extends 더하기, 빼기, 곱하기, 나누기 { }
");

class 계산기 extends 계산기Interclass {
.... 이곳에 자식클래스 계산기의 멤버함수 및 데이터멤버를 정의합니다.
} [/code]
다중 상속으로 생기는 문제점
다중 상속이 가진 문제점은 클래스 상속 구조가 매우 복잡해지고, 멤버 특성의 상속 관계가 모호해 진다는 것입니다.
예를 들면, 만일 동일한 이름의 데이터멤버 x가 더하기, 빼기 클래스에서 각각 정의되어 있을 때 더하기, 빼기 클래스를 다중으로 상속받게 되는 계산기 클래스에서 데이터멤버 x에 접근할 때 더하기 클래스에 있는 데이터멤버 x에 접근해야 할지 아니면 빼기 클래스에 있는 데이터멤버 x에 접근해야 할지 혼란이 발생하게 됩니다. 따라서 각 클래스에서 데이터멤버를 정의할 때는 하위클래스에서 동일한 이름의 데이터멤버를 참조할 경우를 대비하지 않으면 안됩니다. 이러한 문제는 멤버함수를 정의할 때도 동일하게 나타나는 문제입니다.
아래 예와 같이 다중 상속되었을 경우를 보면 후키라이브러리에서는 왼쪽에 있는 자식클래스에서 우선적으로 멤버를 찾게 됩니다. 이 예에서는 더하기에 있는 데이터멤버 또는 멤버함수를 먼저 참조하도록 되어 있습니다. 더하기에서 찾지못하였으면 빼기에서, 빼기에서 찾지 못하였으면 곱하기에서, 곱하기에서 찾지 못하였으면 나누기에서 찾게됩니다. 이러한 규칙은 파이썬과 유사하다고 할 수 있습니다.
[code php;gutter:false] classdefine("
class 계산기Interclass extends 더하기, 빼기, 곱하기, 나누기 { }
");

class 계산기 extends 계산기Interclass {
.... 이곳에 자식클래스 계산기의 멤버함수 및 데이터멤버를 정의합니다.
} [/code]
그러나 이러한 규칙에 의존하여 클래스를 정의하지 말기 바랍니다. 이는 매우 관리하기 힘들고 약간의 실수에도 큰 문제를 발생시킬 수 있기 때문에 가능하면 각 클래스 별로 다른 클래스와 구분할 수 있는 멤버 이름을 사용할 것을 권합니다. 꼭 다중 상속을 이용해서만이 아니더라도 PHP에서는 멤버의 접근 권한(access right)을 임의로 지정할 수 없으며 무조건 public으로 설정되도록 되어 있기때문에 이 문제는 항상 상존한다고 보아야 합니다. C++의 경우를 보면 멤버의 접근 권한이 public 외에도 private, protected를 선택할 수 있으며 private를 지정할 경우에 하위클래스에서 동일한 이름의 멤버를 접근하는데 혼란이 발생하지는 않을 것입니다.

Posted by 방글24