The use of getters and setters for different programming languages [closed]
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 12 years ago.
Improve this questionSo I know there are a lot of questions on getters and setters in general, but I couldn't find something exactly like my question. I was wondering if people change the use of get/set depending on different languages. I started learning with C++ and was taught to use getters and setters. This is what I understand:
In C++ (and Java?), a variable can either be public or private, but we cannot have a mix. For example, I can't have a read-only variable that can still be changed inside the class. It's either all public (can read and change it), or all private (can't read and can only change inside the class). Because of this (and possibly other reasons), we use getters and setters.
In MATLAB, I can control the "setaccess" and "getaccess" properties of variables, so that I can make things read-only (can directly access the property, but can't overwrite it). In this case, I don't feel like I need a getter because I can just do class.property.
Also, in Python it is considered "Pythonic" to not use getters/setters and to only put things into properties if needed. I don't really understand why its OK to have开发者_如何学Go all public variables in Python, because that's opposite of what I learned when I started with C++.
I'm just curious what other people's thoughts are on this. Would you use getters and setters for all languages? Would you only use it for C++/Java and do direct access in MATLAB and Python (which is what I am currently doing)? Is the second option considered bad? For my purposes, I am only referring to simple getters and setters (just return/set the value and do not do anything else).
Thanks!
Actually, getters and setters (as well as public properties hiding these) are very little improvement over public variables, and a pretty good indicator for quasi classes.
It's OK to have all public variables in any language. Yes, I know it's the opposite of what you learned.
OO theory says that there should be a public API that is stable, and private variables, where you can do whatever you want, and an implementation you can change to your hearts delight without changing the API.
And this is correct. But what is not correct is the idea that the private API must be made inaccessible from other classes. This is simply a mistake in the OO theory. It is an idea that sounds reasonable on paper, but in practice has little to go for it, but causes plenty of problems.
For example, many years ago I needed to subclass a widget in Delphi to make it behave slightly differently. Not a lot you see, just a bit. But the code I needed to override called a method that was private, so I couldn't override it. Instead I needed to override both methods. And of course, that other method did things that was really internal, so I ended up basically not subclassing the widget, but duplicating it, just because I did one small change.
OO theory claims this is how it should be, because horror of horror, maybe otherwise my sublclass might stop work with the next version of Delphi, if the superclass changes something internal! Well, so what? In that case I would just fix it.
It's my problem if I use parts of your internal data. You don't need to care. What you need to do is somehow flag that "This bit is internal and might change, use on your own risk". But when you as a developer of a library actively prevents me from using internal bits, you are only causing me problems.
I've now developed almost exclusively with Python for soon to be ten years, and the openness of Python has never caused me problems, and it fact has saved my ass several times (as I can fix framework bugs by simply patching in fixed code at runtime). Delphis standard OO model with different levels of protection caused me problems several times during the two years I worked with it.
The OO Theory is in fact wrong. There is nothing useful in having private members. Everything should be public. And that goes for any language, in my experience.
I don't generally use getters/setters because the presence of them indicates that my class isn't doing enough to be alive.
When I do consider needing them I always create them, no matter whether or not the language supports mixing access wrt variables. Only time I'd consider not doing so is in languages like VB that support "properties" where a function can look just like a variable access. The key reason here is that I don't want clients bound to the fact that the property is implemented by a variable.
Depends on how abstracted you need. For example, I recently needed a getter and setter in C++ when abstracting a Text object. The Direct3D text object just held a string Text member variable. The Direct2D Text object however had to be recreated and recached and that kind of thing. If I had opted for public variables when designing the original abstraction, I would have had to redesign the interface and change all the dependent code. While I agree that getters and setters over certain kinds of class are pointless, there are some cases in which they are necessary.
Of course, languages with properties don't need this kind of thing. But conceptually, they're the same. Defining a property over a variable is just a getter and setter with syntactic sugar, and while I support syntactic sugar, it doesn't change the encapsulation. I wouldn't change my encapsulation design on a language by language basis. Of course, the community opinion on whether or not encapsulation is a good thing is another matter- that's likely the difference that you're seeing. In C++ encapsulation is rated very highly, whereas the Python community cares for it less.
In Matlab, each additional function call incurs some overhead. So if you don't need a setter/getter, because some language feature allows you to do exactly the same, then I really cannot see why you wouldn't want to use the language feature.
Python, being a dynamic scripting language, is less about compile-time constraints, and more about flexibility.
Getters and setters ("property" is just getter + setter) allow for better encapsulation (checking validity, only getter, not setter; implementation details does not matter - e.g. time has hours, minutes, seconds, but how are data actually stored? who cares?), and future extensibility (e.g. code of setter might change, consumers don't care).
In modern efficient languages like C++, there is inlining, so there is no performance cost for simple getters/setters.
Point is, use public fields for structural and simple (small-scale) programming, use getters and setters for large-scale OOP projects.
It should actually be all the same. I always refer from a real life situation, before putting something to public or not. Can everyone have access to the engine of my car?. Most of the time, the answer is no, because it is mine. People may look at it, but they cannot change it, because they want to.
So getters and setters are always important in every language. The only thing is, that it is different in different languages on how to set the access rights. So as you state, if Python
really wants to set everything to public, that seems wrong to me. But setting access rights in MATLAB
to some kind of extend, seems very right to me.
As for the difference in properties and getters. Most of the time, if both are available in a language, there are some rules for that. For example, in C#
, it is encouraged to use properties, when the property behaves like a normal variable and it is ensured that the function is only O(1)
. If the property has more to do, like extra logic, a function should be created instead [Rules of properties in C#
].
Concluding: Everything should be as private
as possible. Create the access points yourself. Properties are getters and setters in a nice layout, because it looks like a variable and does some extra checks if needed. But not too much.
Python and C++ have different principles. C++ and Java are quite “static” and have lots of compile time checks, so you should exploit them when using C++ and Java: public vs. private, const-correctness, etc. Plus they don't have properties, so if you find that you should do some parameter validation, you cannot easily convert a public member variable into a getter–setter pair without changing syntax and breaking existing code. Python, on the other hand, is a dynamic language that allows everybody to do everything: you can override every variable from every module, encapsulation cannot be enforced, there are no static type checks, etc. Python people tend to say “we’re all adults,” and that you should not rely on undocumented behavior and use unit tests instead of compile-time checks. I’m not in the position to judge what is better, but generally you should stick to the established conventions of your language.
You're right - no need for "simple" getters and setters in modern Matlab OOP; the access modifiers that you mentioned are the "Right Way".
In the new MCOS Matlab classes, the syntax for accessing a class property is the same whether you define custom getter/setters or not. Clients can always access property foo as "obj.foo". If you decide to add the special "get.foo" and "set.foo" methods, they are implicitly called by Matlab when a client accesses that property using the "obj.foo" syntax. So it's not really "direct field access" like public fields in Java or C++. It's like Scala's "Uniform Access" model. (I think.) The "." syntax and declarative access controls you mention keep things simple and lets you transparently add custom logic when you need it, without committing to writing boilerplate code up front. The ubiquity of user-defined getters and setters in Java is partially because the language lacks these features.
In old-style Matlab classes, the inverse is true: all fields are private, so you must write your own getter/setters. The convention I've seen is to write a single method with the same name as the property that gets or sets depending on whether you call it as "foo(obj)" or "foo(obj, NewValue)".
Consider this fragment of c++:
class C {
public:
const T &get_t() const { return t; }
void set_t(const T &value) { t = value; }
private:
T t;
};
In this example, member "t" is effectively part of C's public interface, because of the accessor functions. Often, though, the accessor functions are more complicated, performing calculations, managing concurrency, etc. In these cases, access to "t" is encapsulated with the desired operations within the accessor functions.
It's not possible in C++ to encapsulate the access operations with other operations with direct data member access, so we use accessor functions. In fact, we use accessor functions even when simple access is all that's necessary because
if you mix direct access with accessor functions, it's difficult to remember which members use which sort of access, and
it's hard to predict whether you might need your accessors to do more in the future. If you do, and you used accessors, you can change your accessors without changing your public interface (API).
Through properties, Python provides consistency of access using the natural, direct-access syntax, as well as the ability to add functionality to data member access, though (hidden) getters and setters.
Further, data privacy is achieved by convention in python using leading underscores on member names to signal to users that a particular member is not part of the public interface of a class. Users violate the convention, but then they are free to keep both pieces if it breaks. Python programmers call this "We're all adults here" programming.
class C:
def get_t(self):
return self._t
def set_t(self, t):
self._t = t
t = property(get_t, set_t)
In this example, _t is conventionally private, and accessed through its property interface, but still gets share a natural, direct access syntax with other data members.
精彩评论