Download

[Code] Why are some class members of a class public while others need to use Getters/Setters?

Not sure if this has been discussed, and I haven’t seen relevant results when searching here. I am just curious.

Could we have a consistent access methods for these public class members?

For example, RootComponent in an AActor would be accessed through GetRootComponent() and set through SetRootComponent(). But we would have multiple accesses when using Controller in the AActor, such as



AActor->Controller = SomeCustomController; //To set controller
AActor->Controller; //To get controller.


Or



AActor->GetController(); //To get controller, and no setter function.


Just this part is making me curious.

Most likely reason:

Hundreds of people contributing to code over almost two decades, don’t want to change somebody else’s code and risk making breaking changes, just make it public :stuck_out_tongue:

Then why do we need to change RootComponent to have Getters/Setters instead of just directly accessing the member before 4.7? And I am sure there are other class members that were used to be public, and was changed to Getters/Setters that I don’t know of, or I am not familiar with.

I’m not sure if the thread is a complaint or an observation :wink:

Slowly, Epic are working to make all components private with gets/sets unless there are particular reasons not to do so. One example of this; the default mesh that comes with the Character class was made private from 4.6 > 4.7 and we can expect to see more of it in upcoming builds. The reason it isn’t standardised throughout the entire code-base yet is because frankly, it’d be a huge undertaking. As I said, hundreds of people have contributed to the source code at one point or another, in some cases it might have been easier to just mark things as public and get a feature working. “Controller” might just be an example of that, get a feature in and worry about variable scope later.

There’s nothing stopping you from using RootComponent->SomeOperation() or RootComponent = ‘Something’ in the actual class itself. The new Gets/Sets for components are inline ops though, so it might just look cleaner to use them instead and you won’t have any performance overhead.


Assuming you know this already, but just in case: The idea behind this is that you don’t want other people to come along and change the value of that property easily or treat it as some arbitrary thing. Using a Get ensures that whoever is trying to access it is doing it a) on purpose and b) can only treat it as a SceneComponent. It’s entirely possible somebody could write some bogus code that the compiler or intellisense/Vax won’t pick up on.

Getters and setters allow the programmer of those methods to enforce invariants when accessing or setting the member. If you had a completely public variable, you could do anything with it. You could for example set it to null and that would most likely break anything.
With a setter, the programmer can validate the parameter and do other stuff if needed. Compared to my null example, you could first check if the setter parameter isn’t null and after that assign it. If it is null, don’t assign it.
Same goes for getters, there might be other logic in the methods other than just returning the member.

It’s all about data encapsulation: http://en.wikipedia.org/wiki/Encapsulation_(object-oriented_programming)

The impression I get is that Epic is slowly transitioning to private members and data encapsulation. Then, it is good news for me, better if they put in setters along with getters instead of just getters while transitioning.

If they could make it consistent by 4.8, it would be wonderful. Being not so consistent is a bit confusing for me to write consistent codes.

I absolutely agree that total and consistent encapsulation would be great, however, realistically it isn’t going to happen.

Ideally new systems would be written encapsulated, but just as you find it a bit confusing to come in to inconsistent code, people working in existing code that isn’t encapsulated feel strange being the only piece that is encapsulated and tend to follow the pattern of the code they are working in and so a culture of encapsulation is hard to build.

Existing systems will occasionally be encapsulated to allow better control over the members and to ensure necessary side-effects are managed, however, changing the entire engine would be a massive undertaking that would distract us from being able to do anything new for quite awhile. It would cause untold hours of work to users of the engine when they integrated that system. And in some cases, particularly BlueprintReadWrite variables, require new tech to allow us to redirect the existing nodes to using the setters (which honestly is something we need to do anyways, but still more work).

As TheJamsh said … this is the product of an engine that has 15-20 year old code and many systems were originally written in unrealscript where encapsulation could have a non-trivial runtime performance cost.