What good are public variables then?

倖福魔咒の 提交于 2019-11-28 08:54:01

By hiding the variable and adding methods now, the class designer allows for inserting arbitrary code into those methods in the future without breaking tons of code that use the attributes directly.

Also note that providing a lot of accessor/mutator methods is generally a sign that your class design needs another look for possible improvement. Class methods should implement actual logic, not just provide access to each member.

I use public variables only in struct form. For example, I might have a database table that represents a string->value mapping, where value is a composite data structure. I'd just write a structure and use for example std::map<std::string, MyStruct> to represent the database table. I don't need to actually do work on the data, merely be able to look it up and make use of it when required.

As noted in a couple comments, even structs can often benefit from judicial use of methods, for example a couple of common constructors to keep the members sanely initialized, a clear function to reuse the structure, etc.

IMO the most compelling reason for setters/getters is isolating change. If you need to add range checking, for example, if you already have a setter, you can easily do that in your setter without impacting client code. If you don't already have a setter, then all client code needs to be updated to use getters/setters which could be a nightmare.

I agree, in part, with the other answers regarding the use of getter and setter methods to allow for future changes but there is still a fundamental problem, you are exposing the internal data of your object for other objects to modify.

It is better to ask the object to perform some action on the data it holds, via a method, rather than treat the object as a collection of values.

Here's an interesting article on Why Getter and Setter Methods are Evil, it's written with Java in mind but the same applies to C++.

One argument runs something like this:

If code external to the class in question relies directly on a particular member, making a change to that member means changing every piece of code that accesses it. If instead it is accessed by member functions, you can keep that part of the interface the same, and only have to make changes to that class to keep external code working.

Using "getters" and "setters" gives you some flexibility built into the coupling of your objects.

Anything exposed as public becomes part of the contract of that object. If you expose data publicly then it must continue to behave properly when the data values are changed. For struct type objects this may well be appropriate.

Having a high number of getters and setters can be a warning sign that the object is really a struct and it may be better to expose the fields directly. However, I have implemented struct type objects in order to allow fields to have multiple names. Fields could have multiple setters or getters as required allowing name translation between different domains. The real fields had descriptive names. Additional getters and setters used the domain specific codes for those fields.

As other have noted, getters and setters are indicative of the presence of a field. There is no requirement that such a field exist, only that its behavior exists. Making the getters and setters public implies there is a reason for the public to be able to modify or read the value of that field. Think twice about the purpose, and you may change the method name or not make it public.

These are called "getters" and "setters." One good reason to use them is that you can add extra code later without changing the interface. In your example it doesn't look like they do much, but in more complex classes they're practically essential.

OK, As I understand, your question is this: Why make a variable private and then make two functions which just retrieve the value and set the value without any checks? If there were checks, you'd understand, wouldn't you? For example, if you set the hour field of a Time class, checking that hour <= 24 is a good idea.

But when no checks are applied the idea is this: if at some point you decide to change the setting and getting functions, for example, perform some checks in them, the whole code that has been using your class need not be recompiled

Also, the general purpose of encapsulation is that one communicate with the class only via its interface, without knowing how it is implemented. The more inner info you hide, the better.

When do you use public variables? When you make objects that have no behavior. Ones that are just a conglomerate of data. For example, see std::pair. A pair is just a struct, with public first and second.

In general, one cannot give a strict criteria when to use which way, but you'll feel it yourself with gain of experience.

HTh

As Scott Meyers says on Effective C++ book: Avoid data members in the public interface. Why? because it's more easy to code (everything is a member function), also you have more control on the access of that variable, and what Doug T. and the others said about functional abstraction.

If you don't need a class (like in your example) you have the choice of use a struct...

Look this post written by Scott if you don't have the book :)

I cannot agree with this opinion that public members are evil. C++ is not C#. I would always avoid things that I don't really need when coding in C++. Using public members is completely fine if

  • your public variables cannot be set to undefined, out of bounds or somehow corrupted values
  • you know that nobody will try to corrupt your object (meaning that the modules using it know exactly what to do with it)
  • you don't need any other additional checks or object modifications caused by the get/set action
  • you are 100% sure you won't need any of the mentioned things in the future

Despite what some people say, I believe accessing public variable leads to a cleaner code than using some function calls to do practically the same. This of course depends on what kind of project it is and how will the class be used and how it might be used in the future. Writing getters and setter just in case is in my humble opinion useless.

As a reference, read C++ guidelines (C.131)

It is just a basic practice. You design the public interface of a class which can be safely accessed by the callers. If they are just methods, their content can be changed later. If they are public data members you are stck with them forever. You can not change what a public variable does.

Some programming languages (OOP models) use properties for the same idea. If your public interface only consists of code, you can change the inner workings at any time leaving the interface (and other code which is using it) intact. If your public interface contains data, you restrict your future development possibilies.

I know in Java we use public variables, in fact,

public static final

variables as means to specify constants before enumeration was introduced.

For example,

class Direction
{

public static final String NORTH = "north";
...
}

It has been a while I looked into C++, so not sure if there are enumerated types available. You can use the similar code above if enumeration is not available in C++

Getters and setters are indeed a good practice in most cases. But the fact is that your current example is too simple, and therefore is not a good candidate for defending private members access through get/set().

One of the more interesting trends is auto implemented properties. So instead of having to write the getters and setters you just have to write a property and the compiler does the rest. You still have the option of writing the getters and setters, but you don't have to write all of the boiler plate code for what should just be 1 line. If you need to add range checking etc later, you can just create the property the old fashioned way and keep the interface to your class the same.

I have seen this in the latest versions of C#, Objective-C and VB and it can be quite helpful. VB's implementation doesn't offer as much flexibility as C#, but I am sure it will catch up pretty quickly.

I don't care much for writing accessors that do nothing. I have two reasons for this attitude.

  • One of the reasons for doing so is that the code will later be inherited from. I've found this is usually not true in practice. What usually happens is the code is refactored or replaced. The lifespan of code is almost always very short.

  • You're making extra work now for something that might, or might not, happen in the future. This is a variation of the "premature optimization" fault.

There are places where it's a good idea and places where it's not. In most cases I feel the answer is it's not useful.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!