Java-Gaming.org Hi !
Featured games (91)
games approved by the League of Dukes
Games in Showcase (799)
Games in Android Showcase (236)
games submitted by our members
Games in WIP (865)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1] 2
  ignore  |  Print  
  getters and setters vs public vars  (Read 17238 times)
0 Members and 1 Guest are viewing this topic.
Offline bmanmcfly
« Posted 2016-07-09 04:39:36 »

This question isn't related to any particular problem, but more to see the opinions on encapsulation for games.

I know that the idea is to make classes in such a way that code can be reused as simply as possible...

It makes sense when you are dealing with buttons, or tangible objects... however, when you are dealing with objects that are more or less abstract, like a collisionhandler, input handler, etc... and other things that will depend on the structure of the game and not necessarily be reusable elsewhere, is there any reason why it would be better to use "player.getSpeed()" then "player.setSpeed()" vs "player.speed = x"...

So, is there any other reason that I'm missing as to why I should use getters and setters over direct access?
Offline Stranger
« Reply #1 - Posted 2016-07-09 06:01:56 »

The reason for using getters and setters instead of making your members public is that it makes it possible to change the implementation without changing the interface.
Also, many tools and toolkits that use reflection to examine objects only accept objects that have getters and setters. JavaBeans for example must have getters and setters as well as some other requirements.
Also, the fields of a class can be made read-only or write-only.   
 

Anton
Offline Archive
« Reply #2 - Posted 2016-07-09 06:10:42 »

a variable like "speed" in your example would be good (in my opinion) to make public. This is because you cant do:
player.speed++;
player.speed *= 10;
player.speed %= 30;
etc...
easily with getters and setters

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline bmanmcfly
« Reply #3 - Posted 2016-07-09 07:39:56 »

a variable like "speed" in your example would be good (in my opinion) to make public. This is because you cant do:
player.speed++;
player.speed *= 10;
player.speed %= 30;
etc...
easily with getters and setters

Actually, its probably to do with poor planning and execution (being a noob, mostly), but I find myself writing functions where I would want to have multiple return statements....

Like in the collision handler, I would want to return the player position after resolving the collision, the start and end points of the line that was collided, and changing the player speed (from falling to not falling) just as an example, and find it easier to just use class variables directly over get and set... I am quite certain there's no way to return multiple variables of different types.

I was mostly just asking to see if there wasn't any consequences to my laziness beyond that the code would not be easily reusable... I'll wait to see if there are other issues, but you both bring up good points about why it is worth the effort and hassle to use the get and set methods where possible.
Offline Herjan
« Reply #4 - Posted 2016-07-09 08:24:04 »

I am quite certain there's no way to return multiple variables of different types.

You can either pass an object as a parameter and edit it, or return a new instance of a class.
SOLID may also help with a reusable design for your game.
Offline Abuse

JGO Ninja


Medals: 71


falling into the abyss of reality


« Reply #5 - Posted 2016-07-09 11:11:36 »

a variable like "speed" in your example would be good (in my opinion) to make public. This is because you cant do:
player.speed++;
player.speed *= 10;
player.speed %= 30;
etc...
easily with getters and setters

Encapsulation. A class of objects should manage its own state.

If you've got code all over the place directly manipulating the speed of the player (either the member directly, or through getters/setters), then you've failed to properly encapsulate your code.
Offline 65K
« Reply #6 - Posted 2016-07-09 12:09:26 »

Encapsulation and proper dependency management are crucial for writing maintainable software.
What may look today like a valid and convenient shortcut will evolve into an uncontrollable monster over the time. Starting with a bad practice is like injecting a virus into a software system. The next time you will remember it and say, alright, wasn't that bad, it works, I know how things work, only once again. Not to speak of programming with several people.
Even only developing one year on a game is more than enough to leave a mess behind.
Bad, bad practice.

Lethal Running - a RPG about a deadly game show held in a futuristic dystopian society.
Offline ags1

JGO Kernel


Medals: 367
Projects: 7


Make code not war!


« Reply #7 - Posted 2016-07-09 20:29:39 »

Assuming the code is only being used in it's own project, and you get tired of your public variables, then all you have to do is change the public variable to private and fix the broken references. It's no big deal.

If your code is shared across several projects or by several people, then you have an insoluble mess with public non-final mutable variables.

Offline Icecore
« Reply #8 - Posted 2016-07-09 20:32:36 »

short answer:
If you use Var – in 3-5 places – Use public

For else create get/set
"getters / setters" - var changes, can be easily searched (separate) by IDE,
and can help resolve many problems + it can be overwrite
    
getters and setters vs public vars
But you don’t need create get/set for every variable (even if its right style)
Because as result you receive tons of code, that you don’t really need

Less code sometimes better than right pattern style Wink

up:
I am quite certain there's no way to return multiple variables of different types.
You can either pass an object as a parameter and edit it, or return a new instance of a class.
or even
(if you use Fun in one Thread)
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
public void Proc_Collis(){
   Return_Collis.Reset_Data();
   ...
   Return_Collis.have_Collis = true;
   ...
}
class Return_Collis{
   static public have_Collis;
   ....
   static public void Reset_Data(){
      have_Collis = false;
      ...
   }
}

Last known State: Reassembled in Cyberspace
End Transmission....
..
.
Journey began Now)
Offline ClaasJG

JGO Coder


Medals: 43



« Reply #9 - Posted 2016-07-09 21:31:39 »

[...]

Wow, I would never be calm again  Stare
-ClaasJG

My english has to be tweaked. Please show me my mistakes.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline bmanmcfly
« Reply #10 - Posted 2016-07-10 02:01:27 »

I am quite certain there's no way to return multiple variables of different types.

You can either pass an object as a parameter and edit it, or return a new instance of a class.
SOLID may also help with a reusable design for your game.

This makes sense, and gives a different approach to code, IMO at least...
Sounds like its better to start vague and work towards the code to make it work...

ex: start with an entity that has a position and size, and from that is a character that extends an entity, and can move, jump, attack and then either gets extended to an enemy or player which implements...
Offline bmanmcfly
« Reply #11 - Posted 2016-07-10 02:04:15 »

Assuming the code is only being used in it's own project, and you get tired of your public variables, then all you have to do is change the public variable to private and fix the broken references. It's no big deal.

If your code is shared across several projects or by several people, then you have an insoluble mess with public non-final mutable variables.

That's why I was asking, because it's only me, so I was thinking "why should I stress myself out over the grief caused by get/set methods", and you all have offered some very good reasons why its bad form.
Offline Icecore
« Reply #12 - Posted 2016-07-10 11:03:27 »

Every
...
have sense ^^

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
public void Proc_Collis(){
   Return_Collis.Reset_Data();//Always first
   if(!Check_Colis()){
      return;
   }
   Return_Collis.have_Collis = true;
   ///calculate Pos_Offset + Velocity
}
class Return_Collis{
   static public boolean have_Collis;
   static public Vec3 Velocity;
   static public Vec3 Pos_Offset;

   static public void Reset_Data(){
      have_Collis = false;
      Velocity = new Vec3();
      Pos_Offset = new Vec3();
   }
}

Last known State: Reassembled in Cyberspace
End Transmission....
..
.
Journey began Now)
Offline Abuse

JGO Ninja


Medals: 71


falling into the abyss of reality


« Reply #13 - Posted 2016-07-10 11:10:32 »

Every
...
have sense ^^

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
public void Proc_Collis(){
   Return_Collis.Reset_Data();//Always first
   if(!Check_Colis()){
      return;
   }
   Return_Collis.have_Collis = true;
   ///calculate Pos_Offset + Velocity
}
class Return_Collis{
   static public boolean have_Collis;
   static public Vec3 Velocity;
   static public Vec3 Pos_Offset;

   static public void Reset_Data(){
      have_Collis = false;
      Velocity = new Vec3();
      Pos_Offset = new Vec3();
   }
}


If I encountered that in a code base, I'd run for the hills.
Offline Icecore
« Reply #14 - Posted 2016-07-10 11:15:47 »

If I encountered that in a code base, I'd run for the hills.
It can be replaced for instance of class with local variables Wink
1  
2  
3  
4  
5  
6  
7  
8  
public Return_Collis Proc_Collis(){
   Return_Collis ret_Obj = new Return_Collis();// Reset_Data(); in Constructor
   if(!Check_Colis()){
      return ret_Obj;
   }
   ret_Obj.have_Collis = true;
   ///calculate Pos_Offset + Velocity
}

Last known State: Reassembled in Cyberspace
End Transmission....
..
.
Journey began Now)
Offline shadowstryker
« Reply #15 - Posted 2016-07-10 12:19:10 »

a variable like "speed" in your example would be good (in my opinion) to make public. This is because you cant do:
player.speed++;
player.speed *= 10;
player.speed %= 30;
etc...
easily with getters and setters

Encapsulation. A class of objects should manage its own state.

If you've got code all over the place directly manipulating the speed of the player (either the member directly, or through getters/setters), then you've failed to properly encapsulate your code.
In my opinion, pretty much what Abuse is saying here is right. Or, at least, it is what I practice. Truly you shouldn't be modifying class variables from tons and tons of other classes, it should all be managed and maintained in its own class so that it can be retrieved for use in other classes. As a result, unless I am in a hurry and/or don't care about how good my code is (E.g. when I switch from programming in my 3D Game Library to programming in my 3D Game Library test/debug program), I almost always use getters/setters. I've just been taught that doing so was best practice.

I'm browsing through the classes of my 3D Game Library and I can't seem to find any public vars in my code, they all use getters/setters. But then again I am programming using a Component Based Architecture. Another reason for using getters/setters is that it gives you control over mutability.
Offline SHC
« Reply #16 - Posted 2016-07-10 12:51:57 »

I dunno why I read
vars
as
wars
in the title at first, but here are my opinions in that regard. Note that I have changed my style, after coming to know of the 64k method limit on android, but I like this new style, as this is more simple.

Rule #1: Prefer to use public variables when they make sense

For example, take a class which is only a container of data, such as a
Vector2
. Then it is better to leave the variables x and y as public. Using setters and getters is not a good option because it's not clean.

1  
2  
3  
4  
5  
// Clean way, using public variables.
speed.x += 4;

// Not so clean when you use getters and setters
speed.setX(speed.getX() + 4);

Using getters and setters like this will make your code look complex. However do this only when you need no validation on the variables, like in this case. It is a simple data class so keep them as public.

Rule #2: For objects that don't need to be set, consider using
final
and public.


For example, you have to write a class that has a property called position, and it is of type
Vector2
. Now you want your users to be setting its contents and not itself directly. Use the final keyword here, and initialize it once in the constructor.

1  
2  
3  
4  
5  
6  
7  
8  
// This works, and you intend to do this simply.
entity.position.x += 4;

// But this will give an error if you try to assign it.
entity.position = new Vector2();

// And you just do this in the class, pretty simple.
public final Vector2 position = new Vector2();

This gives a benefit that you do not need to evaluate the variable each time for being null, and we can enjoy the simplicity too. Keep in mind that getters and setters are needed if the data requires validation.

Rule #3: Use Getters in case you need the value to be readonly to users and not in that same class.

Yes, in case you are needed to set the value of the variable internally and prevent the user from accessing it, use a getter and make it private or protected. For example, you can do this for FPS value from the game loop so the user is able to get the fps but not set it.

Rule #4: Use Setters in case you need data verification.

Yes, I don't say never use setters, you have to use them when you really need and this is one of such areas. Consider that you have to set a value, like the volume of the playing sound, and it should be in a range.

1  
2  
3  
4  
public void setVolume(float volume)
{
    this.volume = Math.min(1, Math.max(volume, 0));
}

These are the four basic rules that I've taught myself recently after reading a lot of sample android code, and they work great for me so I do recommend them to you. Additionally this removes the function call overhead, as I heard (but am not sure) that invoking virtual functions causes some overhead.

Offline basil_

« JGO Bitwise Duke »


Medals: 418
Exp: 13 years



« Reply #17 - Posted 2016-07-10 13:19:13 »

just to add my 2 cents SHC's description ...

i think this issue should be a no-brainer. getter/setter (simple, without processing) and field read/write access is the same thing ... if using a good IDE, like idea.

you can always track access and refactor all that stuff back and forth by hitting the keyboard with your face (hot-key).
Offline Hydroque

JGO Coder


Medals: 25
Exp: 5 years


I'm always inspiring a good time.


« Reply #18 - Posted 2016-07-10 20:48:49 »

The biggest reasons why I use getters and setters is...

1. They allow immutable classes to be made, where an object manages its own fields. This is why I use the final keyword a lot. It not only helps me make classes immutable, but allows for me to identify variables in code easier (format highlighting), directs meaning to variables without final (value will change), and catch any errors where I have tried to implement something other than my idea I was trying to write down for a function (trying to overwrite variables unnecessarily).

2. when it comes time that you want to change whatever.x = 5 to whatever.setX(5), you will need to go back and change all references to whatever.x with whatever.setX(). This isn't a huge problem in eclipse because of alt shift R. It's a task if something goes wrong and you end up creating getters and setters.

3. This goes along with #1. Getters and setters help you with code suggestions. whatever.get (ctrl + space) gives you a list of all variables. When you don't use getters and setters, the variables are mashed into the functions and have an uncommon name. This makes it hard to search for.

4. Anonymous inner types can modify your getters and setters as they see fit for the specific application.

You think I haven't been monitoring the chat? http://pastebin.java-gaming.org/c47d35366491fHere is a compilation <3
Offline ags1

JGO Kernel


Medals: 367
Projects: 7


Make code not war!


« Reply #19 - Posted 2016-07-10 21:09:38 »

An immutable class doesn't manage its own fields. It's fields don't change. Also I think you are confusing final on a method (cannot override) with final on a field (value fixed at instantiation).

Offline philfrei
« Reply #20 - Posted 2016-07-11 00:36:37 »

The only exception I have to using setters and getters is when I am able to wholly separate some functionality into the mutable and immutable components. The intent is, in part, to help with concurrency issues. I got the idea from reading about functional programming. But that doesn't mean I'm implementing it correctly. In this case, the class with the variables only has variables and no functions whatsoever.

music and music apps: http://adonax.com
Offline nsigma
« Reply #21 - Posted 2016-07-11 09:41:13 »

I almost always use getters and setters, even for final variables unless they're static. However, don't assume using methods for set / get requires you to use JavaBean conventions.  Sometimes a fluent API can be more legible and less verbose.

eg. the audio coding API in Praxis LIVE uses setter / getter methods like -

1  
2  
3  
4  
5  
6  
7  
8  
Osc frequency(double hz) {
  // validate value or invalidate cached data !!
  this.hz = hz;
  return this;
}
double frequency() {
  return this.hz;
}


Which allows for code like -

1  
osc.waveform(SAW).frequency(440).gain(0.4);


If you're doing a lot of updating based on the existing value, you could even override the setter with a method that accepts a function -

1  
osc.frequency(hz -> hz*2);

Praxis LIVE - hybrid visual IDE for (live) creative coding
Offline bmanmcfly
« Reply #22 - Posted 2016-07-11 15:23:32 »

Thanks for all these points...

That has made me decide that it would be better, on the long term, to implement getters and setters, and refactor what I'm working on.... the arguments make sense to prefer get/set over public, in that things will be cleaner.

It is somewhat less intuitive, when it comes to implementing the same logic, and while some classes are easier.  it raises a secondary question:

In order to have a collision detection "object", you would need to pass the parent object at minimum (in order to loop through all objects, NPC's and the player (on the screen, at least), and cast the objects, and then, doesn't that somewhat defeat the purpose, because you give one object almost total control over a secondary object??

Somewhat a pain in the arse, but I guess, better to get into this practice now, than in 2 months, where instead of hours of work would be days or weeks worth of work.  Luckily, all I've really got working is collision detection logic, and player controls... and it turns out that making this conversion will make adding enemies of various types much simpler of a process in the long run.

The bad habits I had picked up with simple games like tetris are apparently haunting me, with a platform game (with polygon objects like terrain, ladders, moving and jump through platforms, and more), that is alot more complex, but I'm already too committed to go back to something simpler...
The changeover requires a different way of thinking about problems, but even since the answers started coming in, and making the effort, it seems that overall its led to less code to accomplish the same amount.

@nsigma :
I think those are called builder classes, I've tried to make some of those before I dropped box2d, and with libgdx, that's how the Vector2 class was made... allows for multiple operations to be performed on single lines of code.  Never had much luck making those types of classes myself.
Offline nsigma
« Reply #23 - Posted 2016-07-11 17:28:04 »

@nsigma :
I think those are called builder classes, I've tried to make some of those before I dropped box2d, and with libgdx, that's how the Vector2 class was made... allows for multiple operations to be performed on single lines of code.  Never had much luck making those types of classes myself.

No, they're not builder classes, although builder classes usually use a similar fluent API (see https://en.wikipedia.org/wiki/Fluent_interface )  Unlike builders, these methods are used to modify an existing object rather than create a new one - they're still getters and setters.  My point was that you don't have to follow the JavaBean conventions.  I use the same principle for animations too -

1  
property.to(5, 0.75).in(3, 1.5).easing(easeIn, easeOut);

Praxis LIVE - hybrid visual IDE for (live) creative coding
Offline bmanmcfly
« Reply #24 - Posted 2016-07-11 21:23:12 »

@nsigma :
I think those are called builder classes, I've tried to make some of those before I dropped box2d, and with libgdx, that's how the Vector2 class was made... allows for multiple operations to be performed on single lines of code.  Never had much luck making those types of classes myself.

No, they're not builder classes, although builder classes usually use a similar fluent API (see https://en.wikipedia.org/wiki/Fluent_interface )  Unlike builders, these methods are used to modify an existing object rather than create a new one - they're still getters and setters.  My point was that you don't have to follow the JavaBean conventions.  I use the same principle for animations too -

1  
property.to(5, 0.75).in(3, 1.5).easing(easeIn, easeOut);


Thanks for the correction... I'm still learning, but keep making breakthroughs on getting better working on this project that is well above my skills.

Its like when I was learning trade work when I was younger, the second I became a journeyman, I thought I could just skip all the annoying things my boss made me do.  First job in I realized WHY you do all that annoying stuff, and it really does just make things easier longer term.

That looks also similar to the tween engine, which I will likely implement in the near future.
Offline Hydroque

JGO Coder


Medals: 25
Exp: 5 years


I'm always inspiring a good time.


« Reply #25 - Posted 2016-07-12 04:57:36 »

An immutable class doesn't manage its own fields. It's fields don't change. Also I think you are confusing final on a method (cannot override) with final on a field (value fixed at instantiation).
Here let me add on.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
public class WindowManager {

private final Window window;

public WindowManager(Window window) {
this.window = window;
}


public Window getWindow() { // manage your object outside of class? or delete this and have WindowManager do it?
return window;
}

}

You think I haven't been monitoring the chat? http://pastebin.java-gaming.org/c47d35366491fHere is a compilation <3
Offline winspeednl
« Reply #26 - Posted 2016-07-31 22:26:02 »

That depends on what you are making.
If you are making a library I recommend Getters and Setters.
It is not required what's however.

Using public variables you are writing a little less code.

Performance
It doesn't really affect the performance, on a really large scale public vars could be faster.

Microsoft gives you Windows. Linux gives you the whole house.
Offline SwampChicken
« Reply #27 - Posted 2016-08-01 05:33:56 »


[...snip...]

1  
2  
3  
4  
5  
// Clean way, using public variables.
speed.x += 4;

// Not so clean when you use getters and setters
speed.setX(speed.getX() + 4);

Using getters and setters like this will make your code look complex.

[...snip...]


Don't 100% agree, if you think as methods being actions then you could "rename" your setters to something more meaningful like:

1  
2  
3  
speed.accelerate(10);

speed.brake(5)
Offline SHC
« Reply #28 - Posted 2016-08-01 06:39:41 »

Don't 100% agree, if you think as methods being actions then you could "rename" your setters to something more meaningful like:

1  
2  
speed.accelerate(10);
speed.brake(5)


That just gives issues, and increases method count, thereby increasing the code size. And on android, there is a limit of 64k methods, it's just not worth it.

Offline KaiHH

JGO Kernel


Medals: 764



« Reply #29 - Posted 2016-08-01 07:41:15 »

That just gives issues, and increases method count, thereby increasing the code size. [...]
In my opinion, this is actually a very nice way of keeping your code clean and keeping your data encapsulated.
It defines an interface between your class and its users based on methods whose behaviour can be specified/documented and best of all, those methods/behaviour can be "contained" within this class. It is far better than changing variables all over the place (either via direct field accesses or via setters). This is especially crucial if the action of "accelerating" or "braking" contains more actions than just changing a single field. You can then "contain" those actions within a single method which is part of the interface of the class. This is a very good thing indeed!
Pages: [1] 2
  ignore  |  Print  
 
 

 
Riven (185 views)
2019-09-04 15:33:17

hadezbladez (4864 views)
2018-11-16 13:46:03

hadezbladez (1785 views)
2018-11-16 13:41:33

hadezbladez (5136 views)
2018-11-16 13:35:35

hadezbladez (1016 views)
2018-11-16 13:32:03

EgonOlsen (4367 views)
2018-06-10 19:43:48

EgonOlsen (5215 views)
2018-06-10 19:43:44

EgonOlsen (2946 views)
2018-06-10 19:43:20

DesertCoockie (3867 views)
2018-05-13 18:23:11

nelsongames (4293 views)
2018-04-24 18:15:36
Java Gaming Resources
by philfrei
2019-05-14 16:15:13

Deployment and Packaging
by philfrei
2019-05-08 15:15:36

Deployment and Packaging
by philfrei
2019-05-08 15:13:34

Deployment and Packaging
by philfrei
2019-02-17 20:25:53

Deployment and Packaging
by mudlee
2018-08-22 18:09:50

Java Gaming Resources
by gouessej
2018-08-22 08:19:41

Deployment and Packaging
by gouessej
2018-08-22 08:04:08

Deployment and Packaging
by gouessej
2018-08-22 08:03:45
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!