4

我已经编写 Java 代码大约 4 个月了。我刚开始使用介绍书的指南编写 android 游戏。在书中,它们没有封装类的任何属性。

前任。

public class GameObject{
    public Vector position;
    public float angle;

    public GameObject(float angle, Vector position){
...

我总是被告知封装属性是一种很好的做法:只允许通过 getter 和 setter 方法访问私有属性。

有比我更有经验的程序员能告诉我哪种方式是创建属性的“正确”编码方式吗?当然,为什么?

然后跟进:我是否应该始终封装类的私有属性并提供 getter 和 setter 方法,或者是否存在公共属性可以的情况?

4

5 回答 5

12

封装是面向对象编程的核心概念之一。在我看来,使用 getter 和 setter 总是很好的做法。您应该避免的一件事是让外部实体随意扰乱您班级的内部结构。

典型的例子,考虑有一个dateOfBirth参数。使用 a settergetter您可以有一个小的验证过程,确保用户不是在未来出生,或者不可能老。您还可以使用 setter 更新一些其他字段,例如年龄。

这种次要验证还可以增强代码的可重用性,因为您无需在调用这些 getter 和 setter 的任何其他类中进行此检查。

于 2013-08-09T06:04:43.960 回答
4

如果我们将纯粹的观点放在一边,我们有两个很好的理由使用 getter 和 setter -

  1. 如果您想修改自己的行为,它可以减少您将来必须做的代码更改量。考虑一下您突然需要进行的以下情况 - 验证某些输入,计算某些字段或在更改时影响其他字段,限制 get 或 set 操作的范围或使其不均匀,修改某些字段的行为继承类或以某种奇怪的方式存储字段。如果您已经有了 getter 和 setter - 这些更改除了更改本身之外不会花费您任何费用。如果没有,您将不得不修改项目中字段的每次使用。

  2. 它允许您实现需要 getter 或 setter 的接口。

于 2013-08-09T06:29:09.470 回答
2

在大多数情况下,您不应将类视为您在外部操作的一组属性,而应将其视为为应用程序提供某些服务的实体。类的大多数属性最终都是私有的,并且没有 get 或 set 方法。

但是也有例外:例如,在某些设置中,您会发现只保存值并且本身几乎没有逻辑或没有逻辑的类。这类类的通常规则是将字段设为私有并提供 get 和 set 方法,因为一旦您将某些内容设为 public,而其他一些类依赖于它,您就无法更改它。例如,您可能希望确保特定字段的值永远不会为空或进行一些其他验证;如果您使用 set 方法,则可以在此处添加检查,但如果该字段是公共的,则您无能为力。另一个例子:你可能想改变字段类型来做一些优化,但是如果字段是公共的,你就无能为力了。

然而,所有的规则都是要被打破的。如果你知道你永远不需要 get 和 set 方法,那么添加它们就没有多大意义了。有些人可能会抱怨“缺乏封装”,但如果类的每个属性都可以从外部读写,那么封装在哪里?

于 2013-08-09T06:36:13.427 回答
0

封装提供了更大的灵活性。它为您提供更多控制,隐藏实现细节。您可以在不提供 set 方法的情况下降低类的可变性。Getter 和 setter 可以有额外的逻辑。无需更改公共 API(getter 和 setter 是公共 API 的一部分)即可更轻松地更改类实现。

于 2013-08-09T06:16:15.170 回答
0

访问器/获取器 - 用于检查实例变量值的公共方法 为了让客户端能够使用一个类,ADT 的实现者通常需要提供一个或多个公共函数以允许用户“查看”(检查) 对象的私有实例变量的当前值。这些“只读”类型的方法称为访问器函数。

例如,类 TwoDice 的两个适当的访问器函数是 getDice1() 和 getDice2(),可用于查找其中一个骰子的当前值。getDice1() 的定义是:

  public int getDice1()
   {
      return dice1 ;
   }

getDice2() 的定义类似。我们可以使用这些函数将第一个骰子的值存储在整数变量 valueOfDie1 中,如下所示:

   TwoDice roll = new TwoDice() ;
   int valueOfDie1 = roll.getDice1() ;

在方法调用roll.getDice1() 中,对象roll 是当前对象(调用该方法的对象),因此将getDice1() 应用于该对象将返回值roll.dice1。

Mutators /Setters - 用于改变实例变量值的公共方法。变异器应包括数据验证,以确保实例变量的值不超出其允许范围。例如,TwoDice 类有一个有趣的属性,即一旦创建了 TwoDice 对象,它的值就不能更改 - 没有提供任何公共方法来允许客户端代码这样做。这样的对象被认为是不可变的,这意味着它们一旦被创建就不能被修改。许多 Java 自己的类具有仅提供不可变对象的特性——其中两个示例是 String 和 Color 类。

类设计者通常提供所谓的 mutator 或 setter 方法,以使客户端代码能够修改对象的值。这是潜在的危险,因为它可能会损害私人数据的安全性。因此,ADT 的实现者必须提供适当的数据验证,以确保将属性(实例变量)的值正确设置在其允许值的范围内。我们的 TwoDice 类的合适的 mutator 方法是 setDice1( int n ) 和 setDice2( int n ),其中第一个的定义如下:

 public void setDice1( int n )
   {
      assert (n >= 1) && (n <= 6) : "value of dice1 out of range: " + n ;
      dice1 = n ;
   } 

这里有趣的是使用一个断言,如果它评估为假,则会导致程序执行被终止。

于 2013-08-09T06:17:25.513 回答