Unreal5/Unreal C++
[U C++] Interface
taene_
2024. 7. 6. 17:24
Interface의 정의
- 객체가 반드시 구현해야 할 행동을 객체와 분리해서 만들고 행동을 하도록 지정하는데 활용되는 타입
- 다형성의 구현, 의존성이 분리된 설계에 유용하게 활용한다.
언리얼 엔진에서 게임 콘텐츠를 구성하는 오브젝트의 설계 예시
- 월드에 배치되는 모든 오브젝트(안 움직이는 오브젝트도 포함)를 Actor라 한다.
- 이 중 움직이는 오브젝트를 Pawn이라 하는데, 길찾기 시스템을 반드시 사용하면서 움직이는 오브젝트이다.
Interface의 특징
- 클래스가 반드시 구현해야 하는 기능을 지정하는데 사용한다.
- C++은 기본적으로 다중 상속을 지원하지만, 언리얼 C++의 인터페이스를 사용해 가급적 축소된 다중 상속의 형태로 구현하는 것이 향후 유지보수에 도움된다.
- 언리얼 C++ 인터페이스를 생성하면 두 개의 클래스를 생성한다.
- U로 시작하는 타입 클래스( 클라스 타입 정보의 제공 )
- I로 시작하는 인터페이스 클래스( 실질적인 설계 및 구현 )
- 객체를 설계할 때 I 인터페이스 클래스를 사용한다.
- U타입 클래스 정보는 런타임에서 인터페이스 구현 여부를 파악하는 용도로 쓰인다.
- 실제로 U타입 클래스에서 작업할 일은 없다.
- 인터페이스에 관련된 구성 및 구현은 I 인터페이스 클래스에서 진행된다.
- 객체를 설계할 때 I 인터페이스 클래스를 사용한다.
- C++ 인터페이스의 특징
- 추상 타입으로만 선언할 수 있는 Java, C#과 달리 언리얼은 인터페이스에도 구현이 가능하다.
- 언리얼 C++ 인터페이스는 추상 타입으로 강제되지 않고, 내부에 기본 함수를 구현할 수도 있다.
Interface의 활용
// LessonInterface.h
#pragma once
#include "CoreMinimal.h"
#include "UObject/Interface.h"
#include "LessonInterface.generated.h"
// This class does not need to be modified.
UINTERFACE(MinimalAPI)
class ULessonInterface : public UInterface
{
GENERATED_BODY()
};
/**
*
*/
class UNREALINTERFACE_API ILessonInterface
{
GENERATED_BODY()
// Add interface functions to this class. This is the class that will be inherited to implement this interface.
public:
virtual void DoLesson() = 0; //abstract 추상 가상 함수(=0)를 선언하면 이 인터페이스를 상속받는 클래스는 반드시 해당 함수를 구현해 줘야한다.
};
// Student.h
#pragma once
#include "CoreMinimal.h"
#include "Person.h"
#include "LessonInterface.h"
#include "Student.generated.h"
/**
*
*/
UCLASS()
class UNREALINTERFACE_API UStudent : public UPerson,public ILessonInterface
{
GENERATED_BODY()
public:
UStudent();
virtual void DoLesson() override;
// ILessonInterface를 상속받았으므로
// 그의 추상 함수인 DoLesson()을 반드시 구현해야 한다.
private:
};
// MyGameInstance.cpp
#include "MyGameInstance.h"
#include "Student.h"
#include "Teacher.h"
#include "Staff.h"
#include "LessonInterface.h"
UMyGameInstance::UMyGameInstance()
{
SchoolName = TEXT("OO대학교");
}
void UMyGameInstance::Init()
{
Super::Init();
TArray<UPerson*> Persons = { NewObject<UStudent>(), NewObject<UTeacher>(), NewObject<UStaff>() };
for (const auto Person : Persons)
{
UE_LOG(LogTemp, Log, TEXT("구성원 이름: %s"), *Person->GetName());
}
for (const auto Person : Persons)
{
ILessonInterface* LessonInterface = Cast<ILessonInterface>(Person);
if (LessonInterface)
{
UE_LOG(LogTemp, Log, TEXT("%s님은 수업에 참여할 수 있습니다."), *Person->GetName());
LessonInterface->DoLesson();
}
else
{
UE_LOG(LogTemp, Log, TEXT("%s님은 수업에 참여할 수 없습니다."), *Person->GetName());
}
}
}