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.
取决于您需要的抽象程度。例如,我最近在抽象 Text 对象时需要 C++ 中的 getter 和 setter。 Direct3D 文本对象仅保存一个字符串 Text 成员变量。然而,Direct2D Text 对象必须重新创建和重新缓存之类的事情。如果我在设计原始抽象时选择公共变量,我将不得不重新设计接口并更改所有依赖代码。虽然我同意某些类的 getter 和 setter 是没有意义的,但在某些情况下它们是必要的。
当然,有属性的语言不需要这种东西。但从概念上讲,它们是相同的。定义变量的属性只是使用语法糖的 getter 和 setter,虽然我支持语法糖,但它不会改变封装。我不会逐个语言地改变我的封装设计。当然,社区对封装是否是一件好事的看法是另一回事——这可能就是您所看到的差异。在 C++ 中,封装的评价非常高,而 Python 社区则不太关心它。
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和C++有不同的原理。 C++ 和 Java 相当“静态”,并且有很多编译时检查,因此在使用 C++ 和 Java 时应该利用它们:公共与私有、const 正确性等。此外,它们没有属性,所以如果您发现尽管您应该进行一些参数验证,但您无法在不更改语法和破坏现有代码的情况下轻松地将公共成员变量转换为 getter-setter 对。另一方面,Python 是一种动态语言,它允许每个人做任何事情:你可以覆盖每个模块中的每个变量,不能强制封装,没有静态类型检查等。Python 人们倾向于说“我们是所有成年人”,并且您不应该依赖未记录的行为并使用单元测试而不是编译时检查。我无法判断哪个更好,但通常您应该遵守您的语言的既定惯例。
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)".
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.
发布评论
评论(10)
实际上,getter 和 setter(以及隐藏这些的公共属性)相对于公共变量来说几乎没有什么改进,并且是 准类。
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.
任何语言中的所有公共变量都可以。是的,我知道这与你学到的相反。
OO理论说应该有一个稳定的公共API和私有变量,你可以在其中做任何你想做的事情,并且可以在不改变API的情况下改变你喜欢的实现。
这是正确的。 但不正确的是必须使其他类无法访问私有 API 的想法。这纯粹是 OO 理论中的一个错误。这个想法在纸面上听起来很合理,但在实践中几乎没有什么用处,反而会带来很多问题。
例如,许多年前,我需要在 Delphi 中对一个小部件进行子类化,以使其行为略有不同。你看到的不多,只是一点点。但是我需要重写的代码调用了一个私有方法,所以我无法重写它。相反,我需要重写这两种方法。当然,其他方法所做的事情实际上是内部的,所以我最终基本上没有子类化该小部件,而是复制它,只是因为我做了一个小更改。
OO理论声称这应该是这样的,因为恐怖中的恐怖,否则如果超类改变了一些内部的东西,也许我的子类可能会停止与下一个版本的Delphi一起工作!嗯,那又怎样?在那种情况下我只会修复它。
如果我使用您的部分内部数据,那就是我的问题。你不需要关心。您需要做的是以某种方式标记“此位是内部的,可能会更改,使用风险自负”。但是,当您作为库的开发人员主动阻止我使用内部位时,您只会给我带来问题。
我现在几乎完全使用 Python 进行开发,已经快有十年了,Python 的开放性从来没有给我带来任何问题,而且它实际上多次救了我的屁股(因为我可以通过简单地在固定代码中修补来修复框架错误)运行时)。 Delphi 的标准 OO 模型具有不同的保护级别,在我使用它的两年里,它多次给我带来了问题。
OO 理论实际上是错误的。拥有私有成员没有任何用处。一切都应该公开。根据我的经验,这适用于任何语言。
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.
我通常不使用 getter/setter,因为它们的存在表明我的类没有做得足够好。
当我确实考虑需要它们时,我总是创建它们,无论该语言是否支持混合访问变量。只有在像 VB 这样支持“属性”的语言中,我才会考虑不这样做,其中函数看起来就像变量访问一样。这里的关键原因是我不希望客户端绑定该属性是由变量实现的事实。
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.
取决于您需要的抽象程度。例如,我最近在抽象 Text 对象时需要 C++ 中的 getter 和 setter。 Direct3D 文本对象仅保存一个字符串 Text 成员变量。然而,Direct2D Text 对象必须重新创建和重新缓存之类的事情。如果我在设计原始抽象时选择公共变量,我将不得不重新设计接口并更改所有依赖代码。虽然我同意某些类的 getter 和 setter 是没有意义的,但在某些情况下它们是必要的。
当然,有属性的语言不需要这种东西。但从概念上讲,它们是相同的。定义变量的属性只是使用语法糖的 getter 和 setter,虽然我支持语法糖,但它不会改变封装。我不会逐个语言地改变我的封装设计。当然,社区对封装是否是一件好事的看法是另一回事——这可能就是您所看到的差异。在 C++ 中,封装的评价非常高,而 Python 社区则不太关心它。
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.
在 Matlab 中,每个额外的函数调用都会产生一些开销。因此,如果您不需要 setter/getter,因为某些语言功能允许您执行完全相同的操作,那么我真的不明白为什么您不想使用该语言功能。
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 作为一种动态脚本语言,较少关注编译时限制,而更多关注灵活性。
getter 和 setter(“属性”只是 getter + setter)允许更好的封装(检查有效性,仅 getter,而不是 setter;实现细节并不重要 - 例如时间有小时、分钟、秒,但数据实际如何存储?关心?),以及未来的可扩展性(例如,setter 的代码可能会改变,消费者不关心)。
在 C++ 等现代高效语言中,存在内联,因此简单的 getter/setter 不会产生性能成本。
要点是,使用公共字段进行结构化和简单(小规模)编程,使用 getter 和 setter 进行大型 OOP 项目。
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.
其实应该都是一样的。在是否公开某些内容之前,我总是参考现实生活中的情况。 每个人都可以使用我汽车的发动机吗?。大多数时候,答案是否定的,因为它是我的。人们可能会看到它,但他们无法改变它,因为他们想改变。
因此 getter 和 setter 在每种语言中总是很重要。唯一的问题是,不同语言中如何设置访问权限是不同的。因此,正如您所说,如果 Python 真的想将所有内容设置为公共,那对我来说似乎是错误的。但是在 MATLAB 中将访问权限设置为某种程度的扩展对我来说似乎非常正确。
至于属性和吸气剂的区别。大多数时候,如果两者都以一种语言提供,则有一些规则。例如,在
C#
中,当属性的行为类似于普通变量并且确保函数仅为O(1)
时,鼓励使用属性。如果该属性有更多要做的事情,例如额外的逻辑,则应创建一个函数 [C#
中的属性规则]。结论:一切都应该尽可能
私有
。自己创建接入点。属性是一个很好的布局中的 getter 和 setter,因为它看起来像一个变量,并且如果需要的话会进行一些额外的检查。但也不过分。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 inMATLAB
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 onlyO(1)
. If the property has more to do, like extra logic, a function should be created instead [Rules of properties inC#
].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和C++有不同的原理。 C++ 和 Java 相当“静态”,并且有很多编译时检查,因此在使用 C++ 和 Java 时应该利用它们:公共与私有、const 正确性等。此外,它们没有属性,所以如果您发现尽管您应该进行一些参数验证,但您无法在不更改语法和破坏现有代码的情况下轻松地将公共成员变量转换为 getter-setter 对。另一方面,Python 是一种动态语言,它允许每个人做任何事情:你可以覆盖每个模块中的每个变量,不能强制封装,没有静态类型检查等。Python 人们倾向于说“我们是所有成年人”,并且您不应该依赖未记录的行为并使用单元测试而不是编译时检查。我无法判断哪个更好,但通常您应该遵守您的语言的既定惯例。
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.
你是对的——在现代 Matlab OOP 中不需要“简单”的 getter 和 setter;您提到的访问修饰符是“正确的方法”。
在新的 MCOS Matlab 类中,无论您是否定义自定义 getter/setter,访问类属性的语法都是相同的。客户端始终可以将 foo 属性作为“obj.foo”访问。如果您决定添加特殊的“get.foo”和“set.foo”方法,当客户端使用“obj.foo”语法访问该属性时,Matlab 会隐式调用它们。所以它并不是像 Java 或 C++ 中的公共字段那样真正的“直接字段访问”。这就像 Scala 的“统一访问”模型。 (我认为。)“。”您提到的语法和声明性访问控制使事情变得简单,并允许您在需要时透明地添加自定义逻辑,而无需预先编写样板代码。 Java 中用户定义的 getter 和 setter 无处不在,部分原因是该语言缺乏这些功能。
在旧式 Matlab 类中,情况正好相反:所有字段都是私有的,因此您必须编写自己的 getter/setter。我见过的约定是编写一个与属性同名的方法,该方法根据您是否将其称为“foo(obj)”或“foo(obj, NewValue)”来获取或设置。
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)".
考虑这个 c++ 片段:
在这个例子中,由于访问器函数的原因,成员“t”实际上是 C 公共接口的一部分。但访问器函数通常更复杂,需要执行计算、管理并发等。在这些情况下,对“t”的访问被封装在访问器函数内所需的操作中。
在 C++ 中不可能将访问操作与直接数据成员访问的其他操作封装在一起,因此我们使用访问器函数。事实上,即使简单访问就足够了,我们也会使用访问器函数,因为
如果将直接访问与访问器函数混合使用,则很难记住哪些成员使用哪种类型的访问,
通过属性,Python 使用自然的直接访问语法提供访问的一致性,以及通过(隐藏的)getter 和 setter 向数据成员访问添加功能的能力。
此外,数据隐私是通过 Python 中的约定实现的,使用成员名称上的前导下划线来向用户表明特定成员不是类的公共接口的一部分。用户违反了约定,但如果损坏了,他们可以自由保留这两个部分。 Python 程序员将此称为“我们都是成年人”编程。
在此示例中,_t 通常是私有的,并通过其属性接口进行访问,但仍然与其他数据成员共享自然的直接访问语法。
Consider this fragment of c++:
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.
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.