与Java的公共领域有什么关系?

我一直在javaworld.com上阅读两篇文章(1) (2) ,关于所有类字段应该是私有的,getter / setter方法也同样糟糕。 对象应该对其拥有的数据起作用,而不是允许访问它。

我目前正在为Connect Four进行大学任务。 在设计程序时,玩游戏的代理商需要访问董事会的状态(因此他们可以决定要移动的内容)。 他们还需要将这一举动传递给游戏,以便将其作为合法举措进行validation。 在决定移动内容时,将片段分组为具有起点和终点的威胁。

Board,Threat和Point对象实际上并没有做任何事情。 它们只是用于存储可以以人类可读方式访问的相关数据。

在设计之初,我将板上的点表示为两个元素int数组,但是在创建点或引用它们的组件时会很烦人。

所以,class级:

public class Point { public int x; public int y; public Point(int x, int y){ this.x = x; this.y = y; } } 

我能想到的各方面都很完美。 除了它打破了我学到的每一条规则。 我犯了罪吗?

公共字段将对象的表示暴露给其调用者,即如果表示必须改变,则调用者也是如此。

通过封装表示,您可以强制调用者如何与其进行交互,并且可以更改该表示,而无需在公共API未更改的情况下修改调用者。 在任何非平凡的程序中,封装都是实现合理可维护性所必需的。 但是,当您需要胶囊时,它们的适当粒度可能比单个类大。 例如,从它操作的Collection的内部表示封装Iterator是没有意义的。

有了这个,让我们看看你的例子:

 public class Point { public int x; public int y; public Point(int x, int y){ this.x = x; this.y = y; } } 

该类的内部表示极不可能改变,因此通过将字段设为私有来隐藏表示的结构没有任何好处。 但是,一旦构造了Point ,我就会阻止调用者修改它:

 public class Point { public final int x; public final int y; public Point(int x, int y){ this.x = x; this.y = y; } } 

因此,实际上希望封装其状态的类可以返回其Point而不泄漏其内部表示,并在其表示中使用给定的Point而不捕获它。 这也非常适合一个点的数学概念,它没有身份或改变状态。

在设计程序时,玩游戏的代理商需要访问董事会的状态(因此他们可以决定要移动的内容)。 他们还需要将这一举动传递给游戏,以便将其作为合法举措进行validation。 在决定移动内容时,将片段分组为具有起点和终点的威胁。

Board,Threat和Point对象实际上并没有做任何事情。 它们只是用于存储可以以人类可读方式访问的相关数据。

现在这听起来像是一个浪费的封装机会:代理人真的不应该被允许任意修改董事会,但仅限于法律行动。 为什么在更新的州居住在class级Board时,为何决定法律行动是什么? 如果Board要自行validation移动,那么没有来电者,特别是没有代理人,可能会违反游戏规则:

 public class Board { // private fields with state // public methods to query state public void perform(Move move) throws IllegalMoveException; } 

将一个字段公开并不总是一种罪恶,但是你严格限制自己,因为你将实现与使用它的类耦合起来。 稍后你想要添加一个监听器,只要设置了X中的值,就会通知你。 没有重构一切,你无法做到这一点。 如果实现setX()并隐藏字段本身,则只需更改setX()的实现即可通知您已对使用此方法的类进行了更改而未对其进行更改。

如果您知道界面不会改变,那么将变量公之于众是完全合法的。 问题是随着程序变得越来越复杂,您需要更改对字段的访问权限,但现代IDE使重构变得容易,所以我想说继续。

是的,不是。

不,如果:你确定你的范围,并且不需要任何需要普通Java属性(getter / setter)的东西,那么它可能不是什么大问题。

是的,if:某些行为可能会改变,就像你需要抽象影响x或y的计算而不影响调用代码,或者你正在使用期望getter和/或setter的东西。

通常,遵循普通的Java属性模式是最容易的 – 它消除了一种风险。 这也是我希望Java具有真正属性的一个原因。

这是c#优于Java的一个优点。 你可以宣布一个有公共领域的类,然后改变你的想法使用一个带有getter和setter的隐藏字段; 但是调用者的语法是一样的

 public class Point { public int X; } 

 public class Point { int m_x; public int X {get {return m_x;} set {m_x = value;} } 

但来电者总是如此

 Point p; pX = 12; 

Java的“规则”并不是绝对的。 在您的情况下,当您仅使用对象存储数据而不提供关键行为时,将字段保留为公共状态是完全可以的。

另一方面,对于您不需要或想要向用户公开的字段,因为它们可能仅在内部上下文中相关,那么您应该将字段标记为私有,并且如果您确实只提供getter和/或setter需要/想要。

对象越复杂,确保操作之间的一致状态就越重要,因此程序员越有可能保持对象状态的良好封装。

我觉得没问题。 如果犯了罪,那至少不是凡人。 向量是另一种方法,但从我收集的内容中,java中的向量需要太多的开销。

公共字段打破了封装规则,即保护数据。 是的,他们确实持有数据但是通过让您的实例变量PUBLIC可以被工作区中的任何类访问。 实例变量既可以被保护也可以被私有。您可以使用您的getter和setter方法,这样您就可以修改类的实例变量所拥有的数据。 通常你的setter方法会有某种validation,这就是为什么我们必须保护腐败数据的实例变量(通过将它们标记为私有或受保护)

在上面的例子中,你有一个构造函数,它正在初始化你的inst。 变量,但是作为此类的开发人员,您可能拥有权限并知道要插入哪些数据以保持类的完整性。 在你的class级上工作的其他人可能不会意识到这一点,并且可能通过打破封装和整个程序来访问你的变量。

考虑x = -10; 当x只能从0到100(例如)。 我建议坚持封装原则。 希望这可以帮助!

有时,规则会预测您可能没有考虑过的使用情况。

如果你创建一个点或一个点的哈希映射怎么办? 为了使你能够按照你希望的方式工作,你应该实现equals()和hashcode()重载,但最好的做法是使对象不可变 – 这样你就不能从下面改变值了设置/图。