What is the point of interfaces if you still have to cast to the interface to use it?

I keep seeing people praise interfaces, gameplay tags in particular, for being fast because they get around casting, but in every example I see, you have to cast anyways to use the function in the interface. Like in this thread:

https://forums.unrealengine.com/t/calling-interface-functions-in-c/323521

Is there a way to use the interface functions (in c++) in actors that don’t implement it such that you don’t need to cast to the interface? For example can anyone show me a way to check if another actor that implements IGameplayTagAssetInterface has a Gameplay Tag, from an actor that doesn’t implement the interface, without casting? Is the benefit from the fact that you’re casting to the interface and not to the actor somehow?

1 Like

Interfaces are good to having to avoid having access to the things that you should not have access to. Maybe you should take a look at Factory Pattern, and you will get the picture. But I’ll give you a small example.

You have a project that contains multiple types of land vehicles (truck, motorcycles, cars… etc). And all of them implement IVehicle which contains method accelerate.

You are in movement component, and you have pawn reference. You don’t know which one it is, and want to accelerate it. Then you just cast pawn to IVehicle and use method accelerate.
Before you say, but I can create base pawn that is vehicle, and they can al inherit from it, I will explain why is that bad. Vehicles can open door, lower windows… etc. Why would Movement component care about that?

So the goal is, do not give someone reference to the whole pawn, some components don’t need whole pawn, but just part of it, and this is why interfaces are good.

In C++, you can just use Cast<IMyInterface> to check if some object implements that interface, and then call needed method.

Yes, you still have to cast, but you only get the part that you need, and avoid having more than you need. It helps a lot with big projects when it comes to maintainance. This is why Interfaces should be segregated which is I in S.O.L.I.D. :slight_smile:
This, combined with CLEAN architecture is a win win situation.

3 Likes

Thanks for that clarification, I haven’t seen those things before, I’ll read them over. I still have some questions though (although those links may answer them).

How does a cast to a pawn as opposed to an interface make maintenance more difficult? If they’re both just places to have functions abstracted (what difference does it make if its in a base class vs an interface)? Also I don’t understand why it matters that the movement component can see the door or lower windows functions, if it never calls them isn’t that the same as if they were never visible through the cast? Do casts actually load the entire pawn like the static meshes etc.?

If the interface doesn’t load the static meshes, then what happens if I reference the static mesh in an override of the interface function like in GetOwnedGameplayTags()?

Sorry for all of the questions, I just want to be clear what the actual use cases of interfaces are.

1 Like

The simple way to descibe (one of?) their goal would been: to provide a common interface for an objects of different nature and implementation.

My real case is an IUnit interface: a way, for example, to access a unit’s hp and deal damage to that unit. So, the some abstract soldiers, obviously, are IUnits. Also my game has a barrels that can be destroyed, hence, also have hp and are also fit the IUnit interface.

This way, when i get a pointer to hit object, i just get it’s IUnit interface and make this unit take damage. This way i don’t care who is exactly on the other side of that pointer.

Mostly such cases can be also solved by having common parent, but in this case: soldiers are ACharacters with ton of stats and networked movement. And all of this stuff have no sense to have common parent with immovable barrel that is only a static mesh with hp and only replicated to client once on game start.

1 Like

How does a cast to a pawn as opposed to an interface make maintenance more difficult? If they’re both just places to have functions abstracted (what difference does it make if its in a base class vs an interface)?

As explained, in order to keep things in one place :).

Also I don’t understand why it matters that the movement component can see the door or lower windows functions, if it never calls them isn’t that the same as if they were never visible through the cast?

It is S in Solid :P. Some junior will come in, use method to open windows in movement component. And then senior joins the company, gets the bug that windows are opened when car break harshly, and last place he will look will be movement component. By using interfaces, you prevent any potential misusage, and separate responsibilities accordingly.

Do casts actually load the entire pawn like the static meshes etc.?

Pawn is loaded anyways, we are talking abou references or pointers here. So when you cast to interface, it only takes those methods and that’s it. Technically it is the whole object, and in Java, if I recall correctly, you can cast it back to the full object. But if packages are separated properly, then you will be unable to do so. Because the Movement component (for example), will only know about the interface, and not about the whole pawn. Which prevents this cast back to the whole object. This is more about the architectual thing. And is explained more in details if you look at the factory pattern tutorials.

If the interface doesn’t load the static meshes, then what happens if I reference the static mesh in an override of the interface function like in GetOwnedGameplayTags() ?

This is your decision to make. By using Interface you decide what will be exposed, and technically you can expose everything you want. But you should also follow up on the KISS principle. And keep it as simple and as stupid as possible, so expose only the simple stuff. And encapsulate control over the pawn.

Sorry for all of the questions, I just want to be clear what the actual use cases of interfaces are.

Don’t be sorry, I’m here to help. :slight_smile:

2 Likes

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.