Interfaces In C++
An interface is an object-oriented programming concept. It is used when different classes need to implement the same functions but it makes no sense for these classes to share a parent. For example, a character in a game may need to be able to interact with non-player characters (NPCs) as well as certain static objects. One could create a parent class that implements interaction functions and then make both the NPCs and static objects inherit from it; however, it may obfuscate the overall class hierarchy of the project. It would also be a complicated process in a huge project with many different NPC and object classes. Using an interface in such situations will make the code more modular and thus easier to read, debug, and maintain.
Interfaces can help you cut down on casting classes saving resources in the process, you can easily implement the same function across classes but interfaces allow you to call the function without knowing the class of the object by calling through the implemented interface instead.
|Interfaces are intended for functionality only! If you need both functionality and data to be shared by unrelated classes, an Actor Component would be a better solution.|
Creating Interfaces in C++
To create a custom interface in UE4, you must inherit from the UInterface class. The easiest way to do it is to right-click anywhere in the Content Browser of the UE4 Editor, select New C++ Class, and then choose Unreal Interface at the bottom of the list of parent classes. Note that two classes will be created: one that starts with a letter U and one that starts with a letter I. Assuming the custom interface is called YourInterface, they will appear like so:
UINTERFACE(MinimalAPI) class UYourInterface : public UInterface
class YOURPROJECT_API IYourInterface
This may seem confusing. As the comment at the top of the header file will tell you, the UYourInterface class is intended to be left empty. It is there only for the UE4 reflection system. On the other hand, IYourInterface is the actual interface class and all your interface functions should go inside it.
To apply the newly created interface to an object of your choice, open its header file, include the header file of your interface, and add the dependency to the object class declaration like so:
class YOURPROJECT_API AInterfaceActor : public AActor, public IYourInterface
The above code snippet shows an Actor class as an example but you can apply an interface to any UObject.
Due to the nature of interfaces, chances are a great many of the interface functions you write will be virtual. When adding an interface to an object you must ensure all appropriate functions are overriden by the object. In case you need to call the parent implementation of some interface function in your object, remember to use
IYourInterface:: instead of
|Usually, each interface function is expected to be overriden by an object that implements the interface. It would seem that making the functions pure virtual would be the best approach. However, Unreal Engine expects every class to be possible to construct (in other words, not abstract) making actually pure virtual functions impossible. If absolutely necessary, one can fake a pure virtual function using the PURE_VIRTUAL macro. In this case, the body of the function still exists but an error will occur if it is ever executed.|
Using Interfaces in C++
To use an interface one must first determine if the given object implements it. Since an object that implements an interface inherits from that interface, you may think that casting the object to the interface class is the most obvious way to find out. This is indeed one of the ways of doing it, as shown in the code snipped below, where the cast will succeed (return non-null) if YourObject does implement YourInterface.
While the above method works, there are two other ways that may be much more convenient depending on the situation. The first one uses the UClass of your object to determine whether the object implements an interface and the second one uses the object itself. The code snippets below show an example of each. Note that here you should use the U-prefixed version of your interface class.
bool bUsesInterface = ClassOfYourObject->ImplementsInterface(UYourInterface::StaticClass());
bool bUsesInterface = YourObject->Implements<UYourInterface>();
Once you have determined that the object does implement the interface, you can call the interface functions the same way you would call any other function of the object.
C++ Interfaces in Blueprints
UInterfaces are Blueprint implementable by default. This means that attempting to use the
BlueprintCallable function specifier will result in a conflict. If you wish to use this specifier on your interface functions, you have to give up the possibility of implementing the interface in Blueprints using the following meta specifier for the interface:
UINTERFACE(MinimalAPI, meta = (CannotImplementInterfaceInBlueprint)) class UYourInterface : public UInterface
On the other hand, if you would like to be able to implement the interface in Blueprints and call some C++ functionality from there, you must use the
BlueprintNativeEvent specifier. Also note that
BlueprintImplementableEvent specifier also works with blueprintable UInterfaces. Refer to UE4 documentation or this blog post by Tom Looman to learn more about the function specifiers mentioned in this section.
Finally, you can always add the
Blueprintable meta specifier to your C++ interface class in case you prefer it to be more visible that your interface is in fact Blueprint implementable.
UINTERFACE(MinimalAPI, meta = (Blueprintable)) class UYourInterface : public UInterface