20200924 UE4 在C++中声明和使用Interfaces

Reference

UE4 – Declaring and using interfaces in C++

In A Word 简而言之

When we declarate a interface, we need to declarate two C++ classes.

  • One extends from UInterface. It should be a empty class, named with prefix ‘U’.
  • Another one can extend from nothing. It should declarate some functions you need, and it should be named with prefix ‘I’.

声明interface的时候,需要声明两个:

  • 一个继承于UInterface,是个空类,以U前缀命名
  • 另一个不用继承于什么,有实际的内容,以I前缀命名
1
2
3
4
5
6
7
8
9
10
11
12
13
14
UINTERFACE(BlueprintType)
class BROADCAST_API UBroadcastListener : public UInterface
{
GENERATED_BODY()
};

class BROADCAST_API IBroadcastListener
{
GENERATED_BODY()
public:

UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Broadcast")
int32 OnBroadcastReceived(const FString& Message);
};

Then you can implement the interface. Your class should extend from the one that really declarte functions, not the empty one.

然后就可以实现这个类了。继承于I起头那个接口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
UCLASS(BlueprintType)
class BROADCAST_API ULogBroadcastListener : public UObject, public IBroadcastListener // We inherit both UObject and IBroadcastListener
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Broadcast")
int32 OnBroadcastReceived(const FString& Message); // This is the prototype declared in the interface
virtual int32 OnBroadcastReceived_Implementation(const FString& Message) override; // This is the declaration of the implementation
};

int32 ULogBroadcastListener::OnBroadcastReceived_Implementation(const FString& Message)
{
UE_LOG(BroadcastLog,Warning,TEXT("Message: %s"), *Message);
}

We first declarate the prototype function(note that the prototype function doesn’t need to be implemented). Then declarate and implement the one named with postfix Implementation.

我们需要先声明一个和接口中签名完全一致的函数,但是不需要定义它。

然后声明和定义一个以Implementation为后缀的函数,这里面写的是我们真正的逻辑。

How to use the interface?

那么,如何使用这个接口呢?

Storing a reference to the interface 使用引用

Let’s say we want to have a IBroadcastListener as a property of a class, so that a user can bind a listener of its choice. This is how it will be defined in the UCLASS:

如果我们想把接口作为一个property引用起来,那么应该使用TScriptInterface

1
2
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Broadcast")
TScriptInterface<IBroadcastListener> BroadcastListenerCopy

Setting the reference programmatically 绑定引用

1
2
3
ULogBroadcastListener* LogBroadcastListener = NewObject<ULogBroadcastListener>(); // Instantiating the ULogBroadcastListener
BroadcastListener.SetObject(LogBroadcastListener); // BroadcastListener is of type TScriptInterface
BroadcastListener.SetInterface(Cast<IBroadcastListener>(LogBroadcastListener));

Calling a method of the interface 调用方法

1
2
UObject* BroadcastListenerObject = BroadcastListener.GetObject();
IBroadcastListener::Execute_OnBroadcastReceived(BroadcastListenerObject, Message); // Message is of type FString

The key point here is in the call to the OnBroadcastReceived method: we need to make a static call on a function of interface named Execute_NameOfTheInterfaceMethod. The first parameter of this function is the object we want to call the function on, and thereafter we have all the parameters we want to pass to this function.

关键在于我们要调用的是一个静态方法Execute_OnBroadcastReceived,第一个参数是实例,第二个参数才是成员函数的参数。

Buy Me A Coffee / 捐一杯咖啡的钱
分享这篇文章~
0%
//