언리얼 C++ 설계(2) - 컴포지션
- 언리얼 C++의 컴포지션 기법을 사용해 오브젝트 포함 관계 설계
- 언리얼 C++이 제공하는 확장 열거형 타입의 선언과 활용
컴포지션
- 객체 지향 설계에서 Has-A 관계를 구현하는 설계 방법
- 복잡한 기능을 가진 거대한 클래스를 효과적으로 설계
- 모던 객체 설계 기법에서는 컴포지션을 효과적으로 설계하는 것을 중요시함.
SOLID
- 좋은 객체지향 설계 패턴을 제작하기 위한 모던 객체 설계 기법
- Single Responsibility Principle(단일 책임 원칙)
- Open-Closed Principle(개방 폐쇄 원칙)
- 기존에 구현된 코드를 변경하지 않으면서 새로운 기능을 추가할 수 있도록 설계
- Liskov Substitution Principle(리스코프 치환 원칙)
- 자식 객체를 부모 객체로 변경해도 작동에 문제 없을 정도로 상속을 단순히 사용
- Interface Segregation Design(인터페이스 분리 원칙)
- 객체가 구현해야 할 기능이 많다면 이들을 여러 개의 단순한 인터페이스들로 분리해 설계
- Dependency Injection Principle(의존성 역전 원칙)
- 구현된 실물보다 구축해야 할 추상적 개념에 의존
- 모던 객체 설계 핵심은 상속을 단순화하고, 컴포지션을 적극 활용해서, 단순한 기능을 가진 다수의 객체를 조합해 복잡한 객체를 구성하는데 있음.
언리얼 엔진에서의 컴포지션 구현 방법
- 방법 1: CDO에 미리 언리얼 오브젝트를 생성해 조합한다.(필수적 포함,
CreateDefaultSubobject())
- 방법 2: CDO에 빈 포인터만 넣고 런타임에서 언리얼 오브젝트를 생성해 조합한다.(선택적 포함,
NewObject())
- Subobject: 내가 소유한 언리얼 오브젝트.
- Outer: 나를 소유한 언리얼 오브젝트.
UENUM()
enum class ECardType : uint8
{
Student = 1 UMETA(DisplayName = "For Student"),
Teacher UMETA(DisplayName = "For Teacher"),
Staff UMETA(DisplayName = "For Staff"),
Invalid
};
#include "MyGameInstance.h"
#include "Student.h"
#include "Teacher.h"
#include "Staff.h"
#include "Card.h"
UMyGameInstance::UMyGameInstance()
{
SchoolName = TEXT("기본학교");
}
void UMyGameInstance::Init()
{
Super::Init();
UE_LOG(LogTemp, Log, TEXT("============================"));
TArray<UPerson*> Persons = { NewObject<UStudent>(), NewObject<UTeacher>(), NewObject<UStaff>() };
for (const auto Person : Persons)
{
const UCard* OwnCard = Person->GetCard();
check(OwnCard);
ECardType CardType = OwnCard->GetCardType();
UE_LOG(LogTemp, Log, TEXT("%s님이 소유한 카드 종류 %d"), *Person->GetName(), CardType);
const UEnum* CardEnumType = FindObject<UEnum>(nullptr, TEXT("/Script/UnrealComposition.ECardType"));
if (CardEnumType)
{
FString CardMetaData = CardEnumType->GetDisplayNameTextByValue((int64)CardType).ToString();
UE_LOG(LogTemp, Log, TEXT("%s님이 소유한 카드 종류 %s"), *Person->GetName(), *CardMetaData);
}
}
UE_LOG(LogTemp, Log, TEXT("============================"));
}

정리
- 생성자 코드를 사용해 언리얼 오브젝트를 생성할 수 있음.
- 언리얼 C++ 컴포지션의 Has-A 관계에 사용되는 용어
- 언리얼 C++이 제공하는 확장 열거형을 사용해 메타 정보를 넣고 활용할 수 있음.