컴포지션 Composition
객체 지향(OOP) 설계는 상속과 컴포지션이 있다.
- 상속 : 부모-자식 관계, 종속의 개념, Is-A관계
- 컴포지션 : 어느 객체가 다른 객체를 소유, Has-A관계
컴포지션은 복합적인 기능을 가진 클래스를 효과적으로 설계하는데 유용하다.
OOP 4가지 특징
- 추상화 : 어떤 객체의 공통적, 본질적 특징을 추출하여 정의
- abstract class, interface
- 상속 : 기존에 구현한 클래스를 재활용해서 구현하는 것. (코드의 재사용)
- 다형성 : 어떤 객체의 속성, 기능이 변화가능
- 메서드 override, overload
- 캡슐화 : 클래스 내의 property, method를 하나의 캡슐로 묶어서 외부 접근을 최소화하는 것
- public, static, private, protected
OOP 5가지 설계원칙 SOLID
- SRP(단일책임 원칙) : 하나의 객체 - 하나의 기능
- OCP(개방폐쇄 원칙) : 기존 코드 변경 X, 기존 코드에 추가O
- LSP(리스코프 치환 원칙) : 상속은 단순하게 (자식을 부모로 변경해도 문제가 없을 정도로)
- ISP(인터페이스 분리 원칙) : 객체가 구현할 기능이 많으면, 여러개의 단순한 인터페이스로 분리
- DIP(의존성 역전 원칙) : 구현된 실물보다 구축해야 할 추상적 개념에 의존
- 고수준 모듈(interface, 추상 클래스)가 저수준 모듈(메인클래스, 객체)이 정의한 추상타입에 의존해야함
- 왜? : 저수준 클래스는 빈번하게 변경되기때문에 자칫 고수준 모듈까지 변경사항으로 인한 영향을 끼칠 수 있기 때문.
모던 객체 설계 기법은
1. 상속 단순화
2. 단순한 기능을 가진 다수의 객체들이 모여 복잡한 객체를 구성
언리얼 컴포지션 구현방법
컴포지션 자체가 2개의 오브젝트중 하나가 다른 하나를 포함하는 형태이므로 최소 2개의 오브젝트가 필요하다.
즉, 기존에 오브젝트를 생성 후 다른 오브젝트를 생성해서 조합해야한다는 뜻.
1. CDO에 미리 서브 오브젝트를 생성한다. CreateDefaultSubobject() API 사용
서브오브젝트 필수적 포함
2. CDO에 서브 오브젝트가 들어올 빈 포인터만 넣고 런타임에서 언리얼 오브젝트를 생성해서 조합한다.
NewObject() API 사용
서브오브젝트 선택적 포함
여기서
- 내가 소유한 언리얼 오브젝트 : SubObject
- 나를 소유한 언리얼 오브젝트 : Outer
실습
1번을 이용해서 실습을 해볼거다.
상황
: Person에 학생, 선생님, 교직원 3명이 있고, Card라는 컴포지션을 만들어서 각각에 부여한다.
학생증, 교사증, 교직원증 이렇게 있는데, 결과적으로 이걸 출력하는게 목표.
1. 카드 만들기
- 컴포지션으로 만들 Card 클래스.
- 카드도 종류가 여러가지(학생증, 교사증등)이므로, enum 열거형을 사용해서 구별할 수 있도록 구현
- 10줄 UENUM() : 이 객체에 대한 정보를 언리얼이 파악하여 정보에 접근할 수 있도록 함.
- 이를 통해 필드마다 메테정보를 넣을 수 있게 만듬. UMETA() : 매크로
- 열거형이 지정되면, 32줄 ECardType으로 변수 지정을 할 수 있다.
- 11줄 enum class는 uint8(byte)가 기본이다.
2. Person에 컴포지션 구현 (Person에 카드 지정, 가져오기)
- 원래 오브젝트에서 다른 오브젝트를 참조할 때는 헤더를 추가해야하지만, 컴포지션은 전방선언을 한다.
(포인터로 선언할거라서 헤더를 추가하지 않으면 의존성이 낮아진다.) - UE4까지는 class UCard* Card로 선언했지만, UE5부터는 TObjectPtr 로 선언한다.
- Person의 생성자에 CreateDefaultSubobject로 컴포지션을 넣어준다.
- 10줄 TEXT는 FName이다.
그리고, Person의 자식인 Student, Teacher, Staff는 상속되어있으므로 그냥 지정만 해주면 된다.
이런식으로
3. 출력하기
현재 카드만들기, Person에 컴포지션 넣기, 각각의 자식객체에 지정하기까지 했다. 그럼 컴포지션이 잘 구현되었는지 확인한다.
위 코드처럼 하면, 이렇게 enum의 숫자가 출력된다.
FindObject()를 사용해서 CardEnumType을 찾아서 출력한다. 여기서 CardMetaData는 Card.h에 선언한 UMETA이다.
'하고싶은거 > Unreal' 카테고리의 다른 글
Part1 10. 언리얼 컨테이너 라이브러리 UCL : TArray, TSet (1) | 2024.03.11 |
---|---|
Part1 09. 언리얼 C++ 설계 : 델리게이트 (0) | 2024.03.10 |
Part1 07. 언리얼 C++ 설계 : 인터페이스 (0) | 2024.03.09 |
Part1 05.06. 언리얼 리플렉션 시스템 (프로퍼티 시스템) (0) | 2024.03.08 |
Part1 04. 언리얼 오브젝트 (0) | 2024.03.03 |
#개발 #게임 #일상
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!