抽象类中的受保护数据
我的问题具体涉及 Java、抽象类和受保护数据的使用。有人告诉我,所有数据都应该是私有的,并且仅使用受保护的 getter/setter。
现在,我知道我们希望保护数据免遭该类的临时用户的直接操作,并且公共数据成员通常是一种值得怀疑的做法。我看过“Java受保护字段与公共getters”(Java受保护字段与公共getters< /a> ),但我仍然怀疑:
protected int i;
在抽象类中比:
private int i;
protected int geti();
protected void seti(int j);
当抽象类恰好为子类和受保护范围提供父级/公共设施时,我只是没有看到不利的一面旨在为儿童提供访问权限,同时保护临时用户的数据。我在上面提到的问题中注意到,大多数答案似乎都解决了为什么数据一般应该是私有的而不是公开的问题。我试图将我的问题专门集中在供孩子使用的抽象父级中存在的数据上。迄今为止我听到的唯一合理的评论是,使用父级受保护的数据(例如上面的 int i)会在子类中留下引用未在子类中声明的变量的代码。这个论点不太引人注目(请参阅基类中的公共受保护数据成员? )您有一天可能想要更改访问权限,现在您必须尊重您的界面。这是一个抽象类,旨在 100% 的时间进行扩展。
谢谢!对书籍的特定标题/页码引用比对“..任何基本 Java 编程文本...”的引用更有帮助
======================= =================== 2010年10月13日
这是一个关于抽象类的问题,也是一个关于受保护数据的问题。我发现令人失望的是,焦点似乎已经转移到数据隐藏在 OOP 中是否是一件好事的问题上(答案:是)。这里有很多深度涉及抽象类的性质,以及它与常规非最终类的不同之处,以及修复抽象父类中数据项的名称和类型以供使用可能有哪些优势孩子们的班级。我认为这里有可能将创新和更大的控制从抽象父类向下扩展到实现子类。我担心一般原则,例如数据隐藏的优点,可能会成为教条,并抑制创新以及新模式和想法的发展。
感谢所有贡献者。
My question involves specifically Java, abstract classes, and the use of protected data. I am being told that all the data should be private, and protected getters/setters used only.
Now, I understand we want to shield data from direct manipulation by casual users of the class, and that public data members in general are a questionable practice. I have looked at "Java protected fields vs public getters" ( Java protected fields vs public getters ), but I still am dubious that:
protected int i;
is worse in an abstract class than:
private int i;
protected int geti();
protected void seti(int j);
I am just not seeing the down side when the abstract class is there precisely to provide parent/common facility to the children classes, and the protected scope is meant to provide access to children, while protecting the data from casual users. I note in the question referenced above, that most of the answers seem to address the issue of why data in general should be private rather than public. I am trying to focus my question specifically on data existing in an abstract parent intended for use by the children. The sole reasonable comment I have heard to date is that using the parents protected data (e.g., int i above) leaves you with code in the child class that references a variable not declared in the child class. Less compelling is the argument (see Common protected data member in base class? ) that you may want to change the access some day, and now you have to honor your interface. This is an abstract class, and is intended to be extended 100% of the time.
Thanks! Specific Title/page# references to books are far more helpful that references to "..any basic Java programming text..."
========================================== 10-13-2010
This was as much a question about abstract classes as it is about protected data. I find it disappointing that the focus seems to have shifted in the responses to whether data hiding is a good thing in OOP (answer: yes). There's a lot of depth here involving the nature of the abstract class, and how it differs from a regular non-final class, and what possible advantages there might be for fixing the names and types of data-items in the abstract parent for use by the child classes. I think there is the possibility here for innovation and greater control being extended down from the abstract parent to the implementing child classes. I am concerned that general principles, such as the advantages of data-hiding, can become dogma, and inhibit innovation and the development of new patterns and ideas.
Thanks to all who contributed.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
如果字段是私有的并且通过 getter 和 setter 进行访问,您将能够重新实现 getter 和 setter(例如,删除字段并从外部源更新/读取值),从而更改“字段”的工作方式不触及任何儿童班级。
这是否值得,这取决于你。
If the field is private and access is through getters and setters, you will be able to reimplement getters and setters (for instance, dropping the field and updating/reading the value from an external source), and thus change how the "field" works without touching any child classes.
Whether this is worth it, that's up to you.
将受保护的方法视为子类的接口,就像公共方法是其他所有人的接口一样。
提供访问器使基类能够维持其状态:如果没有故意的技巧,子类不可能破坏它。
Think of protected methods as an interface for subclasses, in the same way that public methods are an interface for everyone else.
Providing accessors enables the base class to maintain its state: there's no way a subclass would corrupt it without an intentional trick.
访问权限较少不是缺点,而是优点。类应该始终限制对其内部状态的访问尽可能多。不要考虑为什么内部结构应该被隐藏,而是想想为什么它们应该被暴露。在这种情况下,就像在所有情况下一样,除非有充分的理由公开该变量,否则不要公开它。
Having less access isn't a drawback, it's a benefit. Classes should always limit access to as much of their internal state as possible. Don't think of why internals should be hidden, instead think of why they should be exposed. In this case as in every case, unless there is a really good reason to expose the variable then don't expose it.
在 Java 中,除了任何扩展类之外,同一包中的所有成员都可以访问受保护的成员。将字段设置为私有将阻止同一包中的类直接访问它。
还有亚历克斯之前提出的观点。
In Java protected members are accessible to all members in the same package in addition to any extending classes. Making the field private will prevent classes in the same package from directly accessing it.
As well there is the point that alex raised earlier.
如果您不需要您的孩子直接访问它,为什么要让他们访问?
使用 protected 并不是一个缺点。但如果没有必要,也许最好避免它并控制对您字段的访问。
If you don't need your child to directly access it, why would you let them ?
It isn't a down side to use protected. But if it isn't necessary, maybe it's better to avoid it and control access on your fields.
如果有人对您的类进行子类化,并将子类放在与您当前类相同的包中,他们可能想要覆盖您的 getter 和 setter。例如,他们想要确保
i
只能设置为大于 1 的值。除此之外,这实际上取决于您。惯例是,所有东西都有 getter 和 setter。
If someone subclasses your class, and puts the subclass in the same package as your current class, they may want to override your getters and setters. For example, they wantto make sure that
i
may only be set to a value greater than 1.Other than that, it's really up to you. The convention is that there are getters and setters for everything though.
信息隐藏很有价值,即使在通过继承相关的类中也是如此。
除了允许重新实现之外,如上面 alex 所指出的:
Information hiding is valuable, even among classes related by inheritance.
In addition to allowing re-implementation, as noted by alex above:
您想要使用 getters/setters,因为使用
protected int i;
允许字段覆盖(您希望不惜一切代价避免这种情况)。您希望禁止字段覆盖,因为它的工作方式与方法覆盖不同。字段覆盖不会使被覆盖的字段不可访问(引用的类型决定您正在使用字段的哪个实例)。
可访问字段应该是最终的或位于最终的类中。
乍一看,这看起来只会使代码难以阅读,但它会对功能产生影响。假设该字段确实被派生类覆盖,因为没有使用设置器,所以无法自动更新基字段,也无法检测是否有人更改了基字段(因为基值仍然可以访问)并且更新派生字段。很容易想象,基本状态和派生状态可能会不同步,并且错误将很难追踪。简而言之,它会导致 API 非常脆弱。
不幸的是,没有办法防止这种情况,因为用于防止覆盖的
final
关键字也会使字段写入一次。所以没有可写的不可重载的字段。就我个人而言,我对语言设计者允许字段覆盖感到非常惊讶。使用 setter 的优点是每个级别都可以保证其自身状态的完整性,并相信派生类没有弄乱它。字段覆盖只是自找麻烦。
You want to use getters/setters because using
protected int i;
allows for field overriding (which you want to avoid at all costs).You want to disallow field overriding because it works differently than method overriding. Field overriding does not make the overridden field inaccessible (the type of the reference determines which instance of the field you are working with).
Accessible fields should be final or in a class that is final.
At first glance this looks like something that would just make code hard to read but it has implications on functionality. Say the field does get overridden by a derived class, since setters are not being used, there is no way to automagically update the base field and no way to detect if someone has changed the base field (since the base value is still accessible) and update the derived field. It's easy to imagine that the base and derived states could get out of sync and that the errors would be hard to track down. Simply put it makes for a very brittle API.
Unfortunately there is no way to guard against this since the
final
keyword, which protects against overriding, also makes fields write-once. So no writable non-overloadable fields.Personally I'm rather surprised the language designers allowed field overriding at all. The advantage of using setters is that each level can guaranty the integrity of it's own state and trust that derived classes haven't fouled it up. Field overriding is just asking for trouble.