가이드라인: 일반화
주제
실생활에서 여러 가지 것들이 공통 등록 정보를 갖고 있습니다.
예를 들어, 개와 고양이는 동물입니다.
객체는 해당 클래스 간의 일반화를 사용하여 분류할 수 있는 공통적인 등록 정보도 가질 수 있습니다.
공통 등록 정보를 자신들의 클래스로 추출하여 장래에 시스템을 보다 쉽게 변경하고 유지보수할 수 있습니다.
일반화는 한 클래스가 다른 클래스를 상속함을 표시합니다.
상속받는 클래스를 하위라고 합니다.
상속하는 클래스를 상위라고 합니다.
상속은 상위의 정의(해당 객체에 대한 조작, 관계 및 속성과 같은 등록 정보 포함)가 하위 객체에도 올바르다는 것을 의미합니다.
일반화는 하위 클래스에서 상위 클래스로 그려집니다.
일반화는 복잡하고 다중 레벨을 가진 상속 계층 구조를 모델화할 수 있도록
여러 단계에서 발생할 수 있습니다. 일반 등록 정보는 상속 계층 구조의 위쪽에 위치하며
특수 등록 정보는 아래쪽에 위치합니다.
***다른 말로 하면, 일반화를 사용하여 보다 일반적인 개념을 가진 전문화를 모델화할 수 있습니다.
예제
재활용 기계 시스템에서 모든 클래스(캔, 변 및 나무 상자)는
다른 유형의 적립금 항목에 대해 기술합니다.
이들은 동일한 유형 외에 두 개의 공통 등록 정보(높이 및 무게)를 갖고 있습니다.
별도의 클래스인 적립금 항목에서 속성 및 조작을 통해 이러한 등록 정보를 모델화할 수 있습니다.
캔, 병 및 나무 상자는 이 클래스의 등록 정보를 상속하게 됩니다.

캔, 병 및 나무 상자 클래스는 높이 및 무게라는 공통 등록 정보를 갖습니다.
각각은 일반 개념인 적립금 항목을 전문화한 것입니다.
클래스는 일반적으로 한 클래스로부터만 상속을 하지만 다중 상속을 통해 여러 다른 클래스로부터
상속을 할 수 있습니다.
다중 상속을 사용할 경우 인식해야 하는 몇몇 잠재적인 문제점이 있습니다.
- 클래스가 여러 클래스로부터 상속할 경우, 상위의 관계, 조작 및 속성의 이름을 지정하는 방법을
점검해야 합니다.
동일한 이름이 여러 상위에 나타날 경우, 특정 상속 클래스에 대해 이 이름이
나타내는 의미를 기술해야 합니다(예를 들어 선언의 소스를 나타내도록
이름을 규정함).
- 반복 상속이 사용될 경우, 하위가 동일한 상위로부터 한 번 이상 상속합니다.
이런 일이 발생할 경우, 상속 계층 구조는 아래에 표시된 대로
"다이아몬드 형태"를 갖습니다.

복수 및 반복된 상속.
대화 상자가 있는 윈도우 화면 이동 클래스는 윈도우 클래스를 한 번 이상 상속합니다.
이 컨텍스트에서 제기될 수 있는 질문은 "몇 개의 윈도우 속성 사본이 대화 상자가 있는
윈도우 화면 이동 인스턴스에 포함되어 있습니까"입니다.
반복된 상속을 사용할 경우, 의미론에 대한 명확한 정의를 갖고 있어야 합니다.
대부분의 경우, 이는 다중 상속을 지원하는 프로그래밍 언어에 의해 정의됩니다.
일반적으로, 다중 상속을 관리하는 프로그래밍 언어 규칙은 복잡하므로 종종 올바르게 사용하기가 어렵습니다.
따라서 다중 상속은 필요한 때에만 사용하고 항상 주의를 기울이는 것이 좋습니다.
인스턴스화되지 않고 해당 클래스를 상속할 다른 클래스에 대해서만 존재하는 클래스가
추상 클래스입니다. 실제로 인스턴스화된 클래스는 구체적 클래스입니다.
추상적 클래스는 최소한 하나의 유용한 하위를 갖고 있어야 합니다.
예제
창고 처리 시스템의 지게차 위치는 여러 가지 지게차 위치 유형에 공통인
등록 정보를 나타내는 추상적 엔티티 클래스입니다. 이 클래스는
구체적 클래스인 스테이션, 트랜스포터, 기억장치 및 창고에서 지게차 위치 역할을 할 수 있는
모든 객체가 상속합니다. 이러한 모든 객체는 공통 등록 정보를 갖습니다.
이 객체들은 하나 이상의 지게차를 가질 수 있습니다.

상속된 클래스(여기서는 지게차 위치)는 추상적이며
자체에 대해 인스턴스화되지 않습니다.
클래스 스테레오타입은 다른 목적을 가질 수 있기 때문에 한 클래스 스테레오타입으로부터
다른 클래스 스테레오타입으로의 상속은 중요하지 않습니다.
예를 들어, 경계 클래스가 엔티티 클래스를 상속하게 하면
경계 클래스를 몇 가지 유형의 혼성 클래스로 만들 수 있잇습니다.
따라서 동일한 스테레오타입을 가진 클래스 간에만 일반화를 사용해야 합니다.
클래스 간의 두 관계를 표현하기 위해 일반화를 사용할 수 있습니다.
- 서브유형화 - 종속성이 상위의 서브유형임을 지정합니다.
서브유형은 하위가 상위의 구조 및 작동을 상속하며 하위가 상위와 같은 유형임을 의미합니다
(하위는 어떤 상황에서도 모든 상위를 대신할 수 있는 서브유형입니다).
- 서브클래스화 - 종속성이 상위의 서브클래스(서브 유형은 아님)임을 지정합니다.
서브클래스는 하위가 상위의 구조 및 작동을 상속하며 하위가 상위와 같은 유형이 아님을 의미합니다.
여러 클래스에 공통인 등록 정보를 구분한 다음 다른 클래스가 상속하는 별도의 클래스에
이를 배치하거나, 좀더 일반적인 정보를 전문화하는 새 클래스를 작성한 다음
이들이 일반 클래스를 상속하게 함으로써 이와 같은 관계를 작성할 수 있습니다.
두 변형이 동시에 발생할 경우, 클래스 간에 올바른 상속을 설정하는 데는 어려움이 없습니다.
그러나 일부 경우 두 변형은 동시에 발생하지 않으므로 상속을 사용하는 방법을 이해해야 합니다.
최소한 모델에서 각 상속 관계의 목적은 알아야 합니다.
서브유형화한다는 것은 종속성이 어떠한 상황에서도 모든 상위를 대신할 수 있는 서브유형임을 의미합니다.
서브유형화는 다형태성의 특수한 케이스이며
상위의 잠재적 하위를 고려하지 않고 모든 클라이언트(상위를 사용하는 객체)를 설계할 수 있도록 하는
중요한 등록 정보입니다.
이는 클라이언트 객체를 좀더 일반적이고 재사용할 수 있게 만듭니다.
클라이언트가 실제 객체를 사용할 경우, 이는 특별한 방법으로 적용되며
항상 객체가 해당 타스크를 수행하는지를 찾습니다.
서브유형화는 시스템이 서브유형 세트 내에서 변경을 허용함을 보장합니다.
예제
창고 처리 시스템에서 트랜스포터 인터페이스 클래스는
크레인 및 트럭과 같은 모든 운송 유형과의 통신에 필요한 기본 기능을 정의합니다.
클래스는 다른 운송 수단 간에 executeTransport 조작을 정의합니다.

트럭 인터페이스 및 크레인 인터페이스 클래스 모두 트랜스포터
인터페이스를 상속합니다. 즉, 두 클래스 객체 모두 executeTransport 메시지에 응답합니다.
객체는 언제든지 트랜스포터 인터페이스 역할을 대신할 수 있으며
모든 해당 작동을 제공합니다.
따라서 기타 객체(클라이언트 객체)는 트럭 인터페이스 또는 크레인 인터페이스 객체가 메시지에 응답하는지를
알지 못하더라도 트랜스포터 인터페이스 객체로 메시지를 전송할 수 있습니다.
트랜스포터 인터페이스 클래스는 추상적일수는 있으나
자체에 대해 인스턴스화될 수는 없습니다. 이 경우, 트랜스포터 인터페이스는
executeTransport 조작의 사용법만을 정의하는 반면 하위 클래스는 이를 구현합니다.
C++와 같은 일부 객체 지향 언어는 유형 계층 구조로서 클래스 계층 구조를 사용하여 설계자가
설계 모델의 서브유형에 대해 상속을 사용할 수 있게 합니다.
Smalltalk-80과 같은 다른 언어는 컴파일시 유형 점검을 하지 않습니다.
객체가 수신한 메시지에 응답을 하지 않을 경우 오류 메시지가 생성됩니다.
언어에서 유형 점검을 하지 않더라도 서브유형 관계를 나타내기 위해
일반화를 사용하는 것은 좋은 생각입니다.
일부 경우에서는 언어가 이를 허용하는지 여부에 관계 없이 객체 모델 및 소스 코드를
쉽게 이해하고 유지보수할 수 있게 만들어야 합니다. 상속의 사용 여부가 우수한 양식인지 여부는
프로그래밍 언어의 규칙에 달려 있습니다.
서브클래스화는 일반화의 재사용 측면을 구성합니다. 서브클래스화할 때
다른 클래스가 정의한 등록 정보를 상속함으로써 코드의 어떤 부분을 재사용할 수 있는지를 고려하십시오.
서브클래스화는 노동력을 절감하고 특정 클래스를 구현할 때 코드를 재사용할 수 있게 합니다.
예제
Smalltalk-80 클래스 라이브러리에서 사전 클래스는 세트로부터 등록 정보를 상속합니다.

이 일반화의 근거는 사전이 세트의 구현으로부터 일부 일반 메소드 및
기억장치 전략을 재사용할 수 있다는 것입니다.
사전을 세트(키-값 쌍 포함)로 볼 수 있기는 하지만 사전에는 어떠한 유형의 객체도
추가할 수 없기 때문에(키-값 쌍 제외) 사전은 세트의 서브유형이 아닙니다.
사전을 사용하는 객체는 실제로 사전이 세트인지를 인식하지 않습니다.
서브클래스로부터 종종 이해 및 유지보수하기 어려운 비논리적인 상속 계층 구조가 유발될 수 있습니다.
그로므로 다른 방법이 권장되지 않을 경우 프로그래밍 언어를 사용할 때
재사용에만 상속을 사용하는 것은 바람직하지 않습니다.
이러한 유형의 재사용을 유지보수하는 것은 일반적으로 매우 어렵습니다.
세트 클래스에 변경이 발생하면 세트 클래스를 상속하는 모든 클래스의 많은 부분이 변경됩니다.
이를 유념하고 안정된 클래스만 상속하십시오.
상속의 변경 비용은 비싸기 때문에 실제로 상속은 세트 클래스의 구현을 중지시킵니다.
설계에서 일반화 관계를 사용하는지 여부는 프로그래밍 언어에서의 제안된 상속의 사용 및
의미론에 많이 의존합니다.
객체 지향 언어는 클래스 간의 상속을 지원하나 비객체 지향 언어는 지원하지 않습니다.
설계 모델에서 언어 특성을 처리해야 합니다.
상속을 지원하지 않는 언어 또는 다중 상속을 사용 중인 경우
구현 내에서 상속을 시뮬레이트해야 합니다.
이 경우에는 설계 모델 내에서 시뮬레이션을 모델화하고 상속 구조를
기술할 때에는 일반화를 사용하지 않는 것이 더 좋습니다.
일반화를 사용하여 상속 구조를 모델링하고 구현 내에서 상속을 시뮬레이트하면
설계 모델이 손상될 수 있습니다.
상속을 지원하지 않는 언어 또는 다중 상속을 사용할 경우, 구현 내에서 상속을 시뮬레이트해야 합니다.
이 경우에는 설계 모델 내에서 시뮬레이션을 모델화하고
상속 구조를 기술할 때는 일반화를 사용하지 않는 것이 가장 좋습니다.
일반화를 사용하여 상속 구조를 모델화한 다음 구현에서 상속만 시뮬레이트하면 설계가 손상될 수 있습니다.
시뮬레이션 중에 인터페이스 및 기타 객체 등록 정보를 변경해야 할 수 있습니다.
다음 방법 중 하나를 사용하여 인스턴스를 시뮬레이트하도록 권장합니다.
- 하위가 메시지를 상위로 전달할 수 있게 합니다.
- 각 컨텐츠 내에 상위의 코드를 복제합니다. 이 경우 상위 클래스는 작성되지 않습니다.
예제
이 예제에서 하위는 연관 인스턴스인 링크를 통해 메시지를 상위로 보냅니다.

캔, 병 및 나무 상자에 객체에 공통인 작동은 특수 클래스로 지정됩니다.
이 작동이 공통인 객체는 메시지를 창고 품목 객체로 보내 필요할 때 작동을 수행합니다.
|