关于何时使用私有域和受保护域的困惑
Posted
技术标签:
【中文标题】关于何时使用私有域和受保护域的困惑【英文标题】:Confusion on when to use private vs protected fields 【发布时间】:2015-06-17 01:45:01 【问题描述】:我在 SO 中看到用户说受保护的字段不好,因为随着代码的增长它会引入问题。请参考以下代码。
public class Car
private String modelName;
private int yearReleased;
//getters and setters
如果 Car 类由名为 ToyotaCar 的类扩展
public class ToyotaCar extends Car
// Toyota specific stuff
我希望我的 ToyotaCar 对象具有 modelName
和 yearReleased
字段。这就是为什么我决定从 Car 类扩展。但是子类不会继承私有成员(即使我可以使用公共 getter 和 setter 访问这些字段)。现在我的困惑是我是否应该将 Car 类中的文件设置为受保护而不是私有。但人们说这会带来问题。
这是否意味着无论您总是编写什么类,都将字段设为私有?
如果是这样,在哪些情况下使用了受保护的关键字?它仅适用于我们计划在子类中使用的方法吗?
【问题讨论】:
使用吸气剂。任何人都不应该在类的内部闲逛。如果您稍后决定向设置器添加验证怎么办?protected
访问将完全绕过这一点。经验法则是封装一切,类应该有方法而不是变量。
ToyotaCar
实例 do 具有 modelName
和 yearName
字段,即使它们仍然无法通过 Car
之外的方法访问。
说字段是否被继承是没有意义的;这个词实际上并没有严格的定义。
【参考方案1】:
声明变量的受保护关键字用于使这些实例变量对同一包中的所有其他类以及将扩展涉及这些受保护变量的超类的类[子类]可见。
当然,您可以使用 private 或 protected 修饰符声明变量。但是当您将变量声明为私有时,您可以隐藏变量以使其他类无法直接访问它,另一方面,如果您用受保护的声明变量然后你使变量直接访问它而不使用任何getter方法,这违反了OOP原则。
所以在我看来,由于 Car 是所有其他类的超类,例如 ToyotaCar 等。将超类中的变量声明为私有,而在子类中使用 getter 和 setter 方法来读取和写入取决于根据您的需要。这样做就是遵守 OOP 原则。
希望这会有所帮助。
谢谢
【讨论】:
但是如果我们扩展那个超类,我们也可以从其他包访问类的受保护字段吗?不是吗? @DesirePRG,这意味着您说以下陈述是错误的。受保护的访问修饰符 - 对包和所有子类可见。你能告诉我关于受保护修饰符的正确说法吗? @DesirePRG,如果您需要扩展该类,您可以访问其他包的受保护字段。 你不能访问其他类的受保护字段,因为该类在同一个包中。它必须扩展具有受保护字段的类。你说的和我说的不一样 @DesirePRG,您无法访问同一包中其他类的受保护字段。你提到的说法是错误的。访问类的受保护字段的规则:如果在同一个包中具有受保护字段的类 --- 您可以通过创建该类的对象来访问它,并且不需要扩展类 bcoz 该类在同一个包中.如果类在不同的包中具有受保护的字段——您可以通过扩展该类或创建该类的对象在其他类中访问它。【参考方案2】:如果更改子类中的字段非常紧迫(由于特定的设计/模式),那么您应该将您的类字段声明为protected
。
如果不是这样,那么通常更好的方法是执行相同的操作 在父类更新中使用公共/受保护的成员方法 父类中的那些私有字段,然后调用它 来自子类对象的公共/受保护成员方法。
这样你就可以通过从子类的对象调用父类的成员方法来更新那些父类的私有字段来实现。
【讨论】:
【参考方案3】:您自己搞定了:一个好的做法是默认将所有内容设为“私有”。然后,您的特定设计可能需要例如能够在子类中使用某些属性或(最好)某些方法。在这种情况下,您需要将它们移向“受保护” - 但仅限于这种情况。
请记住,使用访问器(getter 和 setter)是完全可以的,并且可以在不破坏封装的情况下完成。
【讨论】:
以上是关于关于何时使用私有域和受保护域的困惑的主要内容,如果未能解决你的问题,请参考以下文章