我应该总是在Java类中使用getter / setter方法,还是有时可以使用公共属性?

时间:2013-08-09 06:01:54

标签: java android class methods attributes

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

实施例

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

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

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

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

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

5 个答案:

答案 0 :(得分:10)

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

典型示例,请考虑使用dateOfBirth参数。使用settergetter,您可以进行一个小的验证过程,确保用户不会在将来出生,或者不可能过时。您还可以使用setter更新其他一些字段,例如age。

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

答案 1 :(得分:3)

如果我们把纯粹的观点放在一边,我们就有两个充分的理由来使用吸气剂和制定者 -

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

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

答案 2 :(得分:0)

封装提供了更大的灵活性。它为您提供更多控制,隐藏实现细节。您可以在不提供set方法的情况下减少类可变性。吸气剂和制定者可以有其他逻辑。更改类实现更容易,无需更改公共API(getter和setter是公共API的一部分)。

答案 3 :(得分:0)

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

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

  public int getDice1()
   {
      return dice1 ;
   }

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

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

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

Mutators / Setters - 用于更改实例变量值的公共方法。 Mutators应包括数据验证,以确保实例变量的值不超过其允许的范围。 例如, 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 ;
   } 

感兴趣的是使用断言,如果求值为false,则导致程序执行终止。

答案 4 :(得分:0)

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

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

所有规则都应该被打破。如果您知道自己永远不需要获取和设置方法,那么添加它们并不重要。有些人可能会抱怨&#34;缺乏封装&#34;但是如果类的每个属性都可以从外部读取和写入,那么封装是什么?