实践中的私有成员与公共成员(封装有多重要?)

发布于 2024-07-05 19:48:09 字数 1448 浏览 13 评论 0原文

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(22

趁微风不噪 2024-07-12 19:48:09

这取决于。 这是必须务实决定的问题之一。

假设我有一个代表一个点的类。 我可以为 X 和 Y 坐标设置 getter 和 setter,或者我可以将它们公开并允许对数据进行自由读/写访问。 在我看来,这是可以的,因为该类的行为就像一个美化的结构——一个可能附加了一些有用函数的数据集合。

然而,在很多情况下,您不想提供对内部数据的完全访问,而是依赖类提供的方法与对象进行交互。 一个例子是 HTTP 请求和响应。 在这种情况下,允许任何人通过网络发送任何内容都是一个坏主意 - 它必须由类方法进行处理和格式化。 在这种情况下,类被认为是一个实际的对象,而不是一个简单的数据存储。

这实际上取决于动词(方法)是否驱动结构或者数据是否驱动结构。

It depends. This is one of those issues that must be decided pragmatically.

Suppose I had a class for representing a point. I could have getters and setters for the X and Y coordinates, or I could just make them both public and allow free read/write access to the data. In my opinion, this is OK because the class is acting like a glorified struct - a data collection with maybe some useful functions attached.

However, there are plenty of circumstances where you do not want to provide full access to your internal data and rely on the methods provided by the class to interact with the object. An example would be an HTTP request and response. In this case it's a bad idea to allow anybody to send anything over the wire - it must be processed and formatted by the class methods. In this case, the class is conceived of as an actual object and not a simple data store.

It really comes down to whether or not verbs (methods) drive the structure or if the data does.

氛圍 2024-07-12 19:48:09

我倾向于非常严格地遵守规则,即使这只是我自己的代码。 出于这个原因,我真的很喜欢 C# 中的属性。 它使得控制所给出的值变得非常容易,但您仍然可以将它们用作变量。 或者将集合设置为私有,然后将其设置为公开,等等。

I tend to follow the rule pretty strictly, even when it's just my own code. I really like Properties in C# for that reason. It makes it really easy to control what values it's given, but you can still use them as variables. Or make the set private and the get public, etc.

來不及說愛妳 2024-07-12 19:48:09

我几乎一直遵守这方面的规则。 对我来说有四种情况 - 基本上是规则本身和几个例外(均受 Java 影响): 可被

  1. 当前类之外的任何内容使用,通过 getters/setters 访问
  2. 类内部的使用通常以“this”开头很明显,它不是一个方法参数,
  3. 意味着要保持非常小的东西,例如传输对象 - 基本上是属性的直接镜头; 所有公共的
  4. 需要非私有的以进行某种扩展

I follow the rules on this almost all the time. There are four scenarios for me - basically, the rule itself and several exceptions (all Java-influenced):

  1. Usable by anything outside of the current class, accessed via getters/setters
  2. Internal-to-class usage typically preceded by 'this' to make it clear that it's not a method parameter
  3. Something meant to stay extremely small, like a transport object - basically a straight shot of attributes; all public
  4. Needed to be non-private for extension of some sort
闻呓 2024-07-12 19:48:09

我更喜欢尽可能长时间地保持成员私有,并且只能通过 getter 访问它们,即使是在同一个类中也是如此。 我还尽量避免将 setter 作为初稿,以尽可能推广价值风格对象。 经常使用依赖注入,您通常有 setter,但没有 getter,因为客户端应该能够配置对象,但(其他人)不知道实际配置的内容,因为这是一个实现细节。

问候,
奥利

I prefer to keep members private as long as possible and only access em via getters, even from within the very same class. I also try to avoid setters as a first draft to promote value style objects as long as it is possible. Working with dependency injection a lot you often have setters but no getters, as clients should be able to configure the object but (others) not get to know what's acutally configured as this is an implementation detail.

Regards,
Ollie

虫児飞 2024-07-12 19:48:09

是的,封装很重要。 公开底层实现(至少)会造成两件事错误:

  1. 混淆职责。 调用者不需要或不想了解底层实现。 他们应该只是希望班级完成其工作。 通过暴露底层实现,你的类并没有完成它的工作。 相反,它只是将责任推给调用者。
  2. 将您与底层实现联系起来。 一旦公开了底层实现,您就与它绑定了。 例如,如果您告诉调用者,下面有一个集合,您就无法轻松地将集合交换为新的实现。

无论您是直接访问底层实现还是只是复制所有底层方法,这些(和其他)问题都适用。 您应该公开必要的实现,仅此而已。 保持实现私有使得整个系统更易于维护。

Yes, encapsulation matters. Exposing the underlying implementation does (at least) two things wrong:

  1. Mixes up responsibilities. Callers shouldn't need or want to understand the underlying implementation. They should just want the class to do its job. By exposing the underlying implementation, you're class isn't doing its job. Instead, it's just pushing the responsibility onto the caller.
  2. Ties you to the underlying implementation. Once you expose the underlying implementation, you're tied to it. If you tell callers, e.g., there's a collection underneath, you cannot easily swap the collection for a new implementation.

These (and other) problems apply regardless of whether you give direct access to the underlying implementation or just duplicate all the underlying methods. You should be exposing the necessary implementation, and nothing more. Keeping the implementation private makes the overall system more maintainable.

迷途知返 2024-07-12 19:48:09

作为一个必须维护过去由许多人编写的几年前的代码的人,我很清楚,如果一个成员属性被公开,它最终会被滥用。 我什至听到人们不同意访问器和修改器的想法,因为这仍然没有真正达到封装的目的,即“隐藏类的内部工作原理”。 这显然是一个有争议的话题,但我的观点是“将每个成员变量设为私有,主要考虑类必须做什么(方法),而不是如何做”我们将让人们改变内部变量”。

As someone having to maintain several-year-old code worked on by many people in the past, it's very clear to me that if a member attribute is made public, it is eventually abused. I've even heard people disagreeing with the idea of accessors and mutators, as that's still not really living up to the purpose of encapsulation, which is "hiding the inner workings of a class". It's obviously a controversial topic, but my opinion would be "make every member variable private, think primarily about what the class has got to do (methods) rather than how you're going to let people change internal variables".

挖鼻大婶 2024-07-12 19:48:09

基本上,信息隐藏与代码清晰度有关。 它的设计目的是让其他人更容易扩展您的代码,并防止他们在使用您的类的内部数据时意外地创建错误。 它基于没有人阅读评论的原则,尤其是其中包含说明的评论。

示例:我正在编写更新变量的代码,并且我需要绝对确保 Gui 发生更改以反映更改,最简单的方法是添加访问器方法(又名“Setter”) ),调用该方法而不是更新数据。

如果我将这些数据公开,并且在不通过 Setter 方法的情况下更改变量(并且这种情况在每次脏话时间都会发生),那么有人将需要花费一个小时的调试来找出更新未显示的原因。 在较小程度上,这同样适用于“获取”数据。 我可以在头文件中添加注释,但很可能没有人会读它,直到出现非常非常错误的情况。 使用 private 强制执行意味着不会犯错误,因为它会显示为易于定位的编译时错误,而不是运行时错误。

根据经验,唯一需要将成员变量设为 public 并省略 Getter 和 Setter 方法的情况是,如果您想绝对清楚地表明更改它不会产生任何副作用; 特别是如果数据结构很简单,比如一个简单地保存两个变量作为一对的类。

这应该是相当罕见的情况,因为通常您想要副作用,并且如果您创建的数据结构非常简单以至于您不需要(例如配对),那么已经有是标准库中提供的一种更高效的编写方式。

话虽如此,对于大多数一次性无扩展的小程序(例如您在大学获得的程序)来说,这比任何事情都更“好实践”,因为您会在编写它们的过程中记住它们,然后您就可以记住它们。我会把它们交给你,并且永远不会再碰代码。 另外,如果您编写数据结构是为了了解它们如何存储数据而不是作为发布代码,那么有一个很好的论点是 Getters 和 Setters 不会有任何帮助,并且会妨碍学习体验。

只有当您进入工作场所或大型项目时,您的代码很可能会被不同人编写的对象和结构调用,因此使这些“提醒”变得强大就变得至关重要。 无论这是否是一个单身男子的项目,都令人惊讶地无关紧要,原因很简单,“六周后的你”就像同事一样是不同的人。 而“六周前的我”往往被证明是懒惰的。

最后一点是,有些人非常热衷于信息隐藏,如果您的数据不必要地公开,他们会感到恼火。 最好是幽默一下他们。

Basically, information hiding is about code clarity. It's designed to make it easier for someone else to extend your code, and prevent them from accidentally creating bugs when they work with the internal data of your classes. It's based on the principle that nobody ever reads comments, especially ones with instructions in them.

Example: I'm writing code that updates a variable, and I need to make absolutely sure that the Gui changes to reflect the change, the easiest way is to add an accessor method (aka a "Setter"), which is called instead of updating data is updated.

If I make that data public, and something changes the variable without going through the Setter method (and this happens every swear-word time), then someone will need to spend an hour debugging to find out why the updates aren't being displayed. The same applies, to a lesser extent, to "Getting" data. I could put a comment in the header file, but odds are that no-one will read it till something goes terribly, terribly wrong. Enforcing it with private means that the mistake can't be made, because it'll show up as an easily located compile-time bug, rather than a run-time bug.

From experience, the only times you'd want to make a member variable public, and leave out Getter and Setter methods, is if you want to make it absolutely clear that changing it will have no side effects; especially if the data structure is simple, like a class that simply holds two variables as a pair.

This should be a fairly rare occurence, as normally you'd want side effects, and if the data structure you're creating is so simple that you don't (e.g a pairing), there will already be a more efficiently written one available in a Standard Library.

With that said, for most small programs that are one-use no-extension, like the ones you get at university, it's more "good practice" than anything, because you'll remember over the course of writing them, and then you'll hand them in and never touch the code again. Also, if you're writing a data structure as a way of finding out about how they store data rather than as release code, then there's a good argument that Getters and Setters will not help, and will get in the way of the learning experience.

It's only when you get to the workplace or a large project, where the probability is that your code will be called to by objects and structures written by different people, that it becomes vital to make these "reminders" strong. Whether or not it's a single man project is surprisingly irrelevant, for the simple reason that "you six weeks from now" is as different person as a co-worker. And "me six weeks ago" often turns out to be lazy.

A final point is that some people are pretty zealous about information hiding, and will get annoyed if your data is unnecessarily public. It's best to humour them.

み零 2024-07-12 19:48:09

当至少满足以下条件之一时,封装就很重要:

  1. 除了您之外的任何人都将使用您的类(或者他们会破坏您的不变量,因为他们不阅读文档)。
  2. 任何不阅读文档的人都会使用您的类(否则他们会破坏您仔细记录的不变量)。 请注意,此类别包括两年后的您。
  3. 将来某个时候,有人会继承你的类(因为当字段的值发生变化时,可能需要采取额外的操作,所以必须有一个setter)。

如果它只适合我,并且在少数地方使用,并且我不打算继承它,并且更改字段不会使该类假定的任何不变量无效,只有这样我偶尔会做出现场公众。

Encapsulation is important when at least one of these holds:

  1. Anyone but you is going to use your class (or they'll break your invariants because they don't read the documentation).
  2. Anyone who doesn't read the documentation is going to use your class (or they'll break your carefully documented invariants). Note that this category includes you-two-years-from-now.
  3. At some point in the future someone is going to inherit from your class (because maybe an extra action needs to be taken when the value of a field changes, so there has to be a setter).

If it is just for me, and used in few places, and I'm not going to inherit from it, and changing fields will not invalidate any invariants that the class assumes, only then I will occasionally make a field public.

北城半夏 2024-07-12 19:48:09

请记住在对象上调用方法的语义。 方法调用是一种非常高级的抽象,可以通过编译器或运行时系统以各种不同的方式实现。

如果您调用的方法的对象存在于同一进程/内存映射中,则编译器或虚拟机可以很好地优化该方法以直接访问数据成员。 另一方面,如果该对象位于分布式系统中的另一个节点上,那么您无法直接访问它的内部数据成员,但您仍然可以通过向其发送消息来调用其方法。

通过对接口进行编码,您可以编写不关心目标对象存在于何处、如何调用其方法的代码,甚至不关心它是否是用相同语言编写的。


在实现集合所有方法的对象示例中,可以肯定该对象实际上是一个集合。 所以也许在这种情况下继承会比封装更好。

Keep in mind the semantics of invoking methods on an object. A method invocation is a very high level abstraction that can be implemented my the compiler or the run time system in a variety of different ways.

If the object who's method you are invoking exists in the same process/ memory map then a method could well be optimized by a compiler or VM to directly access the data member. On the other hand if the object lives on another node in a distributed system then there is no way that you can directly access it's internal data members, but you can still invoke its methods my sending it a message.

By coding to interfaces you can write code that doesn't care where the target object exists or how it's methods are invoked or even if it's written in the same language.


In your example of an object that implements all the methods of a collection, then surely that object actually is a collection. so maybe this would be a case where inheritance would be better than encapsulation.

无可置疑 2024-07-12 19:48:09

这一切都是为了控制人们可以用你给他们的东西做什么。 你的控制力越强,你就能做出越多的假设。

另外,从理论上讲,您可以更改底层实现或其他内容,但因为在大多数情况下:

private Foo foo;
public Foo getFoo() {}
public void setFoo(Foo foo) {}

它有点难以证明。

It's all about controlling what people can do with what you give them. The more controlling you are the more assumptions you can make.

Also, theorectically you can change the underlying implementation or something, but since for the most part it's:

private Foo foo;
public Foo getFoo() {}
public void setFoo(Foo foo) {}

It's a little hard to justify.

全部不再 2024-07-12 19:48:09

C# 属性“模拟”公共字段。 看起来很酷,语法确实加快了创建这些 get/set 方法的速度

C# Properties 'simulate' public fields. Looks pretty cool and the syntax really speeds up creating those get/set methods

过期情话 2024-07-12 19:48:09

我的倾向是尽可能将所有事情保密。 这使得对象边界尽可能清晰地定义,并使对象尽可能地解耦。 我喜欢这个,因为当我必须重写第一次(第二次、第五次?)次搞砸的对象时,它会将损坏保留在较少数量的对象中。

如果将对象耦合得足够紧密,则将它们组合成一个对象可能会更简单。 如果您充分放松耦合约束,您就会回到结构化编程。

如果您发现一堆对象只是访问器函数,那么您可能应该重新考虑您的对象划分。 如果您没有对该数据执行任何操作,它可能属于另一个对象的一部分。

当然,如果您正在编写类似库之类的东西,您希望界面尽可能清晰明了,以便其他人可以针对它进行编程。

My tendency is to try to make everything private if possible. This keeps object boundaries as clearly defined as possible and keeps the objects as decoupled as possible. I like this because when I have to rewrite an object that I botched the first (second, fifth?) time, it keeps the damage contained to a smaller number of objects.

If you couple the objects tightly enough, it may be more straightforward just to combine them into one object. If you relax the coupling constraints enough you're back to structured programming.

It may be that if you find that a bunch of your objects are just accessor functions, you should rethink your object divisions. If you're not doing any actions on that data it may belong as a part of another object.

Of course, if you're writing a something like a library you want as clear and sharp of an interface as possible so others can program against it.

尤怨 2024-07-12 19:48:09

让工具适合工作...最近我在当前的代码库中看到了一些类似这样的代码:

private static class SomeSmallDataStructure {
    public int someField;
    public String someOtherField;
}

然后这个类在内部使用来轻松传递多个数据值。 它并不总是有意义,但如果您只有数据,没有方法,并且您没有将其暴露给客户端,我发现它是一个非常有用的模式。

我最近使用的是一个 JSP 页面,其中显示了一个数据表,在顶部以声明方式定义。 因此,最初它是在多个数组中,每个数据字段一个数组...这最终导致代码相当难以遍历,因为字段在定义中不彼此相邻,而这些字段将一起显示...所以我创建了一个简单的像上面这样的类将它们组合在一起......结果是真正可读的代码,比以前要多得多。

道德...有时您应该考虑“接受的坏”替代方案,如果它们可以使代码更简单且更易于阅读,只要您仔细考虑并考虑后果...不要盲目接受您听到的所有内容。

这就是说......公共 getter 和 setter 几乎等同于公共字段......至少本质上(有一点更多的灵活性,但它仍然是一个糟糕的模式,适用于你拥有的每个字段)。

即使java标准库也有一些 public 的情况字段

Fit the tool to the job... recently I saw some code like this in my current codebase:

private static class SomeSmallDataStructure {
    public int someField;
    public String someOtherField;
}

And then this class was used internally for easily passing around multiple data values. It doesn't always make sense, but if you have just DATA, with no methods, and you aren't exposing it to clients, I find it a quite useful pattern.

The most recent use I had of this was a JSP page where I had a table of data being displayed, defined at the top declaratively. So, initially it was in multiple arrays, one array per data field... this ended in the code being rather difficult to wade through with fields not being next to eachother in definition that would be displayed together... so I created a simple class like above which would pull it together... the result was REALLY readable code, a lot more so than before.

Moral... sometimes you should consider "accepted bad" alternatives if they may make the code simpler and easier to read, as long as you think it through and consider the consequences... don't blindly accept EVERYTHING you hear.

That said... public getters and setters is pretty much equivalent to public fields... at least essentially (there is a tad more flexibility, but it is still a bad pattern to apply to EVERY field you have).

Even the java standard libraries has some cases of public fields.

郁金香雨 2024-07-12 19:48:09

当我让对象变得有意义时,它们就会更容易使用并且更容易维护

例如:Person.Hand.Grab(howquick, how much);

诀窍在于不要将成员视为简单的值,而是将其视为对象本身。

When I make objects meaningful they are easier to use and easier to maintain.

For example: Person.Hand.Grab(howquick, howmuch);

The trick is not to think of members as simple values but objects in themselves.

临风闻羌笛 2024-07-12 19:48:09

我认为这个问题确实将封装的概念与“信息隐藏”混淆了
(这不是批评家,因为它似乎确实符合“封装”概念的常见解释)

但是对我来说,“封装”是:

  • 将多个项目重新分组到容器中的过程
  • 容器本身重新分组项目

假设您正在设计一个纳税人系统。 对于每个纳税人,您可以将孩子的概念封装

  • 一个代表孩子的孩子列表
  • 中,其中的映射考虑到来自不同父母的孩子,
  • 一个对象Children(不是Child)它将提供所需的信息(例如孩子的总数)

这里有三种不同类型的封装,2种由低级容器(列表或映射)表示,一种由对象表示。

通过做出这些决定,您不会

  • 将该封装设为公开、受保护或私有:仍然需要选择“信息隐藏”来进行
  • 完整的抽象(您需要细化对象 Children 的属性,并且您可能决定创建一个对象子对象,从纳税人系统的角度来看,它只会保留相关信息)
    抽象是选择对象的哪些属性与您的系统相关以及哪些必须完全忽略的过程。

所以我的观点是:
该问题的标题可能是:
实践中的私人成员与公共成员(信息隐藏有多重要?)

不过,只是我的 2 美分。 我完全尊重人们可能将封装视为一个包括“信息隐藏”决策的过程。

然而,我总是尝试区分“抽象”-“封装”-“信息隐藏或可见性”。

I would argue that this question does mix-up the concept of encapsulation with 'information hiding'
(this is not a critic, since it does seem to match a common interpretation of the notion of 'encapsulation')

However for me, 'encapsulation' is either:

  • the process of regrouping several items into a container
  • the container itself regrouping the items

Suppose you are designing a tax payer system. For each tax payer, you could encapsulate the notion of child into

  • a list of children representing the children
  • a map of to takes into account children from different parents
  • an object Children (not Child) which would provide the needed information (like total number of children)

Here you have three different kinds of encapsulations, 2 represented by low-level container (list or map), one represented by an object.

By making those decisions, you do not

  • make that encapsulation public or protected or private: that choice of 'information hiding' is still to be made
  • make a complete abstraction (you need to refine the attributes of object Children and you may decide to create an object Child, which would keep only the relevant informations from the point of view of a tax payer system)
    Abstraction is the process of choosing which attributes of the object are relevant to your system, and which must be completely ignored.

So my point is:
That question may been titled:
Private vs. Public members in practice (how important is information hiding?)

Just my 2 cents, though. I perfectly respect that one may consider encapsulation as a process including 'information hiding' decision.

However, I always try to differentiate 'abstraction' - 'encapsulation' - 'information hiding or visibility'.

静待花开 2024-07-12 19:48:09

@VonC

您可能会发现国际标准化组织的“开放分布式处理参考模型”很有趣。 它定义:“封装:对象中包含的信息只能通过对象支持的接口上的交互来访问的属性。”

我试图证明信息隐藏是这个定义的关键部分:
http://www.edmundkirwan.com/encap/s2.html

问候,

艾德。

@VonC

You might find the International Organisation for Standardization's, "Reference Model of Open Distributed Processing," an interesting read. It defines: "Encapsulation: the property that the information contained in an object is accessible only through interactions at the interfaces supported by the object."

I tried to make a case for information hiding's being a critical part of this definition here:
http://www.edmundkirwan.com/encap/s2.html

Regards,

Ed.

落花浅忆 2024-07-12 19:48:09

我发现很多 getter 和 setter 都是代码味道,而程序的结构并不是这样设计得很好。 您应该查看使用这些 getter 和 setter 的代码,并查找真正应该属于该类的功能。 在大多数情况下,类的字段应该是私有实现细节,并且只有该类的方法可以操作它们。

同时拥有 getter 和 setter 等于该字段是公共的(当 getter 和 setter 很简单/自动生成时)。 有时最好将字段声明为公共,这样代码会更简单,除非您需要多态性或框架需要 get/set 方法(并且您无法更改框架)。

但在某些情况下,拥有 getter 和 setter 也是一个很好的模式。 一个例子:

当我创建应用程序的 GUI 时,我尝试将 GUI 的行为保留在一个类 (FooModel) 中,以便可以轻松进行单元测试,并在另一个类 (FooView) 中实现 GUI 的可视化只能手动测试。 视图和模型通过简单的粘合代码连接起来; 当用户更改字段 x 的值时,视图会在模型上调用 setX(String),这反过来可能会引发模型其他部分发生的事件更改后,视图将使用 getter 从模型中获取更新的值。

在一个项目中,有一个 GUI 模型,有 15 个 getter 和 setter,其中只有 3 个 get 方法是微不足道的(以便 IDE 可以生成它们)。 所有其他都包含一些功能或重要的表达式,例如以下内容:

public boolean isEmployeeStatusEnabled() {
    return pinCodeValidation.equals(PinCodeValidation.VALID);
}

public EmployeeStatus getEmployeeStatus() {
    Employee employee;
    if (isEmployeeStatusEnabled()
            && (employee = getSelectedEmployee()) != null) {
        return employee.getStatus();
    }
    return null;
}

public void setEmployeeStatus(EmployeeStatus status) {
    getSelectedEmployee().changeStatusTo(status, getPinCode());
    fireComponentStateChanged();
}

I find lots of getters and setters to be a code smell that the structure of the program is not designed well. You should look at the code that uses those getters and setters, and look for functionality that really should be part of the class. In most cases, the fields of a class should be private implementation details and only the methods of that class may manipulate them.

Having both getters and setters is equal to the field being public (when the getters and setters are trivial/generated automatically). Sometimes it might be better to just declare the fields public, so that the code will be more simple, unless you need polymorphism or a framework requires get/set methods (and you can't change the framework).

But there are also cases where having getters and setters is a good pattern. One example:

When I create the GUI of an application, I try to keep the behaviour of the GUI in one class (FooModel) so that it can be unit tested easily, and have the visualization of the GUI in another class (FooView) which can be tested only manually. The view and model are joined with simple glue code; when the user changes the value of field x, the view calls setX(String) on the model, which in turn may raise an event that some other part of the model has changed, and the view will get the updated values from the model with getters.

In one project, there is a GUI model which has 15 getters and setters, of which only 3 get methods are trivial (such that the IDE could generate them). All the others contain some functionality or non-trivial expressions, such as the following:

public boolean isEmployeeStatusEnabled() {
    return pinCodeValidation.equals(PinCodeValidation.VALID);
}

public EmployeeStatus getEmployeeStatus() {
    Employee employee;
    if (isEmployeeStatusEnabled()
            && (employee = getSelectedEmployee()) != null) {
        return employee.getStatus();
    }
    return null;
}

public void setEmployeeStatus(EmployeeStatus status) {
    getSelectedEmployee().changeStatusTo(status, getPinCode());
    fireComponentStateChanged();
}
森罗 2024-07-12 19:48:09

在实践中,我总是只遵循一条规则,即“没有一刀切”的规则。

封装及其重要性是您的项目的产物。 什么对象将访问您的界面,他们将如何使用它,如果他们对成员拥有不需要的访问权限,这会重要吗? 在实施每个项目时,您需要问自己这些问题以及类似的问题。

In practice I always follow only one rule, the "no size fits all" rule.

Encapsulation and its importance is a product of your project. What object will be accessing your interface, how will they be using it, will it matter if they have unneeded access rights to members? those questions and the likes of them you need to ask yourself when working on each project implementation.

一袭白衣梦中忆 2024-07-12 19:48:09

我的决定基于模块内代码的深度。
如果我正在编写模块内部的代码,并且不与外界交互,我不会用 private 封装太多东西,因为它会影响我的程序员性能(我编写和重写代码的速度)。

但对于作为模块与用户代码的接口的对象,我遵守严格的隐私模式。

I base my decision on the Code's depth within a module.
If I'm writting code that is internal to a module, and does not interface with the outside world I don't encapsulate things with private as much because it affects my programmer performance (how fast I can write and rewrite my code).

But for the objects that server as the module's interface with user code, then I adhere to strict privacy patterns.

清浅ˋ旧时光 2024-07-12 19:48:09

当然,无论您编写内部代码还是供其他人(甚至您自己,但作为一个包含的单元)使用的代码,这都会有所不同。任何要在外部使用的代码都应该有一个定义良好/记录良好的接口,您可以使用该接口。想要尽可能少地改变。

对于内部代码,根据难度,您可能会发现现在用简单的方法做事会更少工作,并且稍后会付出一些代价。 当然,墨菲定律将确保短期收益将被多次消除,因为稍后您需要更改未能封装的类的内部结构,因此必须进行广泛的更改。

Certainly it makes a difference whether your writing internal code or code to be used by someone else (or even by yourself, but as a contained unit.) Any code that is going to be used externally should have a well defined/documented interface that you'll want to change as little as possible.

For internal code, depending on the difficulty, you may find it's less work to do things the simple way now, and pay a little penalty later. Of course Murphy's law will ensure that the short term gain will be erased many times over in having to make wide-ranging changes later on where you needed to change a class' internals that you failed to encapsulate.

爱,才寂寞 2024-07-12 19:48:09

特别是对于使用要返回的集合的示例,此类集合的实现似乎可能会发生变化(与更简单的成员变量不同),从而使封装的效用更高。

话虽这么说,我有点喜欢 Python 处理它的方式。 成员变量默认是公共的。 如果您想隐藏它们或添加验证,可以提供一些技术,但这些被认为是特殊情况。

Specifically to your example of using a collection that you would return, it seems possible that the implementation of such a collection might change (unlike simpler member variables) making the utility of encapsulation higher.

That being said, I kinda like Python's way of dealing with it. Member variables are public by default. If you want to hide them or add validation there are techniques provided, but those are considered the special cases.

我为君王 2024-07-12 19:48:09

大多数现有答案都没有解决这里存在的一个实际问题。 封装以及向外部代码公开干净、安全的接口总是很棒的,但当您编写的代码打算由空间和/或时间上较大的“用户”基础使用时,这一点就更为重要。 我的意思是,如果您计划让某人(甚至您)在未来很好地维护代码,或者如果您正在编写一个将与来自多个其他开发人员的代码进行交互的模块,那么您需要考虑更多与编写一次性或完全由您编写的代码相比,要小心。

老实说,我知道这是多么糟糕的软件工程实践,但我通常会首先将所有内容公开,这使得记住和输入内容的速度稍快一些,然后在有意义时添加封装。 如今,最流行的 IDE 中的重构工具使得您使用的方法(添加封装还是删除封装)的相关性比以前要低得多。

There's a practical concern here that isn't being addressed by most of the existing answers. Encapsulation and the exposure of clean, safe interfaces to outside code is always great, but it's much more important when the code you're writing is intended to be consumed by a spatially- and/or temporally-large "user" base. What I mean is that if you plan on somebody (even you) maintaining the code well into the future, or if you're writing a module that will interface with code from more than a handful of other developers, you need to think much more carefully than if you're writing code that's either one-off or wholly written by you.

Honestly, I know what wretched software engineering practice this is, but I'll oftentimes make everything public at first, which makes things marginally faster to remember and type, then add encapsulation as it makes sense. Refactoring tools in most popular IDEs these days makes which approach you use (adding encapsulation vs. taking it away) much less relevant than it used to be.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文