为了简单的类而放弃 getter 和 setter 可以吗?
我正在创建一个非常简单的类来表示 3D 空间中的位置。
目前,我只是让用户直接访问和修改各个 X
、Y
和 Z
值。换句话说,它们是公共成员变量。
template <typename NumericType = double>
struct Position
{
NumericType X, Y, Z;
// Constructors, operators and stuff...
};
这背后的原因是,因为 NumericType
是一个模板参数,所以我不能依赖有一种体面的方法来检查值的完整性。 (我怎么知道用户不希望用负值表示位置?)因此,添加 getter 或 setter 来使界面复杂化是没有意义的,而且直接访问应该因其简洁性而受到青睐。
Pos.X = Pos.Y + Pos.Z; // Versus...
Pos.SetX(Pos.GetY() + Pos.GetZ());
这是良好实践的例外吗?我的代码的(假设的)未来维护者会追捕我并打我的脸吗?
I'm making a very simple class to represent positions in 3D space.
Currently, I'm just letting the user access and modify the individual X
, Y
and Z
values directly. In other words, they're public member variables.
template <typename NumericType = double>
struct Position
{
NumericType X, Y, Z;
// Constructors, operators and stuff...
};
The reasoning behind this is that, because NumericType
is a template parameter, I can't rely on there being a decent way to check values for sanity. (How do I know the user won't want a position to be represented with negative values?) Therefore, there's no point in adding getters or setters to complicate the interface, and direct access should be favored for its brevity.
Pos.X = Pos.Y + Pos.Z; // Versus...
Pos.SetX(Pos.GetY() + Pos.GetZ());
Is this an okay exception to good practice? Will a (hypothetical) future maintainer of my code hunt me down and punch me in the face?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
使用 getter 和 setter 背后的想法是能够执行其他行为,而不仅仅是设置值。推荐这种做法是因为您可能想要在课堂上改进很多东西。
使用 setter 的常见原因(可能还有更多):
如果您认为您的代码永远不会使用或需要上述任何内容,那么按原则编写 getter 和 setter 绝对不是一个好习惯。它只会导致代码膨胀。
编辑:与普遍的看法相反,使用 getter 和 setter 不太可能帮助您更改类的内部表示,除非这些更改很小。尤其是个人成员设置者的存在,使得这种改变变得非常困难。
The idea behind using getters and setters is to be able to perform other behavior than just setting a value. This practice is recommended because there are a multitude of things you might want to retrofit into your class.
Common reasons to use a setter (there are probably more):
If you think your code will never, ever use or require any of the above, then writing getters and setters by principle is definitely not good practice. It just results in code bloat.
Edit: contrarily to popular belief, using getters and setters is unlikely to help you in changing the internal representation of the class unless these changes are minor. The presence of setters for individual members, in particular, makes this change very difficult.
如果 getter 和 setter 获取/设置您可能以多种方式实现的抽象值,那么它们实际上只是一个重要的设计选择。但是,如果您的类如此简单并且数据成员如此基本以至于您需要直接公开它们,那么只需将它们公开即可!你会得到一个漂亮、便宜的聚合类型,没有任何装饰,而且它是完全自我记录的。
如果您确实想要将数据成员设为私有,但仍授予对其的完全访问权限,只需将单个访问器函数重载一次,如
T & access()
并一次作为const T &访问()常量
。编辑:在最近的一个项目中,我只是使用元组作为坐标,并具有全局访问器函数。也许这可能有用:
Getters and setters are really only an important design choice if they get/set an abstract value that you may have implemented in any number of ways. But if your class is so straight-forward and the data members so fundamental that you need to expose them directly, then just make them public! You get a nice, cheap aggregate type without any frills and it's completely self-documenting.
If you really do want to make a data member private but still give full access to it, just make a single accessor function overloaded once as
T & access()
and once asconst T & access() const
.Edit: In a recent project I simply used tuples for coordinates, with global accessor functions. Perhaps this could be useful:
我花了一段时间,但我跟踪了这个旧的 Stroustrup 采访,他自己讨论了暴露数据结构与封装类: http://www.artima.com/intv/goldilocks3.html
更深入地了解细节,现有答案中可能缺少/低估了某些维度。封装的好处随着以下方面的增加而增加:
外部
”实现,则封装的好处会大大减少Took me a while, but I tracked this old Stroustrup interview down, where he discusses exposed-data structs versus encapsulated classes himself: http://www.artima.com/intv/goldilocks3.html
Getting more heavily into specifics, there's are dimensions to this that may be missing / understated in existing answers. The benefits of encapsulation increase with:
extern
" implementation of a specific translation unittypedef
s for their types, such that a proxy object can be substituted and support identical client-code usage while invoking different implementation如果你做了一些非常简单的事情,你的解决方案可能就很好。
如果您后来意识到球坐标系中的计算更容易或更快(并且您需要性能),那么您可以信赖这一点。
If you do some very easy stuff your solution could be just fine.
If you later realize that calculations in a spherical coordinate system are much easier or faster (and you need performance), you can count on that punch.
对于这样的众所周知的结构来说是可以的:
但是,如果您需要的不仅仅是“只是 3D 向量”的类型,那么您应该将其包装在另一个类中,作为私有成员,然后通过成员函数和附加功能成员函数公开 x、y 和 z。
It is ok for such well known structure that :
However, if you need more than a type that "just is a 3D vector", then you should wrap it in another class, as private member, that would then expose x, y and z through member functions and additional features member functions.
语言和编译器很好地支持这种情况(通过专门化)。
没有实际意义的争论——见上文。
我不认为是这样。您的问题意味着验证应该存在,但不值得实现/支持,因为您选择在实现中使用
模板
,并且不专门适合您的语言功能已经选择了。通过这种方法,接口似乎只得到部分支持——那些缺少的实现只会污染客户端的实现。The language and compilers support this case well (via specialization).
Moot argument -- see above.
I don't think it is. Your question implies validation should exist, but it's not worth implementing/supporting because you've chosen to use a
template
in your implementation, and not specialize appropriate for the language feature you've chosen. By that approach, the interface only appears to be partially supported -- those missing implementations will just pollute clients' implementations.