101

您如何决定将参数传递给方法还是简单地将它们声明为对所有对象方法可见的对象实例变量?

我更喜欢将实例变量保存在类末尾的列表中,但是随着程序的增长,这个列表会变得更长。我想如果一个变量被传递得足够频繁,它应该对所有需要它的方法都是可见的,但是我想知道,“如果一切都是公开的,那么根本不需要传递任何东西!”

4

5 回答 5

60

由于您指的是实例变量,因此我假设您正在使用面向对象的语言。在某种程度上,何时使用实例变量、如何定义它们的范围以及何时使用局部变量是主观的,但在创建类时可以遵循一些经验法则。

  • 实例变量通常被认为是类的属性。将这些视为将从您的类中创建的对象的形容词。如果您的实例数据可用于帮助描述对象,那么可以肯定的是,它是实例数据的不错选择。

  • 在方法范围内使用局部变量来帮助它们完成工作。通常,一个方法应该具有获取一些数据、返回一些数据和/或处理/运行对一些数据的算法的目的。有时,将局部变量视为帮助方法从头到尾的方式会有所帮助。

  • 实例变量作用域不仅是为了安全,也是为了封装。不要假设“目标应该是保持所有变量私有”。在继承的情况下,将变量设置为受保护通常是一个不错的选择。您无需将所有实例数据标记为公开,而是为需要访问外部世界的对象创建 getter/setter。不要让它们全部可用 - 只有你需要的那些。这将贯穿整个开发生命周期——从一开始就很难猜到。

当谈到在类中传递数据时,如果不看一些代码,就很难说你正在做的事情是好的做法。有时,直接对实例数据进行操作就可以了;其他时候,不是。在我看来,这是随着经验而来的——随着你的面向对象思维能力的提高,你会发展出一些直觉。

于 2008-12-06T10:45:27.220 回答
48

这主要取决于您存储在变量中的数据的生命周期。如果数据仅在计算期间使用,则将其作为参数传递。如果数据绑定到对象的生命周期,则使用实例变量。

当您的变量列表变得太长时,考虑将类的某些部分重构为新类可能是一个好点。

于 2008-12-06T10:39:51.193 回答
24

在我看来,实例变量仅在跨调用使用数据时才是必需的。

这是一个例子:

myCircle = myDrawing.drawCircle(center, radius);

现在让成像 myDrawing 类使用 15 个辅助函数来创建 myCircle 对象,每个函数都需要中心和半径。它们仍然不应设置为 myDrawing 类的实例变量。因为他们再也不会被需要了。

另一方面,myCircle 类需要将中心和半径都存储为实例变量。

myCircle.move(newCenter);
myCircle.resize(newRadius);

为了让 myCircle 对象在进行这些新调用时知道它的半径和中心是什么,它们需要存储为实例变量,而不仅仅是传递给需要它们的函数。

所以基本上,实例变量是一种保存对象“状态”的方法。如果变量不需要知道对象的状态,那么它不应该是实例变量。

至于公开一切。它可能会让你的生活更轻松。但它会回来困扰你。豌豆不要。

于 2008-12-06T10:47:12.427 回答
4

恕我直言:

如果变量构成实例状态的一部分,那么它应该是一个实例变量——classinstance HAS-A instancevariable。

如果我发现自己反复将某些东西传递给实例的方法,或者我发现我有大量实例变量,我可能会尝试查看我的设计,以防我遗漏了某些东西或在某处做了糟糕的抽象。

希望能帮助到你

于 2008-12-06T10:40:35.637 回答
3

当然,在类中保留一个大的公共变量列表很容易。但即使凭直觉,您也可以看出这不是要走的路。

在您要使用它之前定义每个变量。如果变量支持特定方法的功能,请仅在该方法的范围内使用它。

还要考虑安全性,公共类变量容易受到来自“外部”代码的不必要更改的影响。您的主要目标应该是使所有变量保持私有,并且任何不是的变量都应该有充分的理由这样做。

关于在堆栈中一直传递参数,这会很快变得丑陋。一个经验法则是保持你的方法签名干净和优雅。如果您看到许多方法使用相同的数据,请确定它是否足够重要以成为类成员,如果不是,请重构您的代码以使其更有意义。

它归结为常识。仔细想想你在哪里以及为什么要声明每个新变量,它的功能应该是什么,并从那里决定它应该在哪个范围内。

于 2008-12-06T10:39:52.940 回答