何时使用对象实例变量与将参数传递给方法


93

如何在将参数传递给方法与简单地将其声明为对所有对象的方法可见的对象实例变量之间做出决定?

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


1
如果您有特定的示例,则可能会得到更直接有用的答案
brabster

Answers:


55

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

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

  • 在方法范围内使用局部变量来帮助它们完成工作。通常,方法应具有获取一些数据,返回一些数据和/或对某些数据进行处理/运行算法的目的。有时,将局部变量视为帮助方法自始至终的方法会有所帮助。

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

在围绕类传递数据时,如果不看一些代码就很难说您正在做的是一种好习惯。有时,直接对实例数据进行操作是可以的。其他时候不是。我认为,这是经验带来的-随着面向对象的思维能力的提高,您将形成一些直觉。


我的答案是将此答案添加到H-Man2答案(生命周期)中。当且仅当它是对象的持久状态时,它才应该是成员属性。也就是说,该值本身在当前方法堆栈的范围之外才有意义。
大卫·罗德里格斯(DavidRodríguez)-德里贝斯

我的直觉是同意David和H-MAn2。但是,我正在阅读Robert c Martin的“简洁代码”,在第3章中,他重构代码将某些东西从方法参数移到成员变量,因为拥有很多参数是不好的。总而言之,我想如果您的类仅负责一项职责,那么对象的生存期与该计算的生存期是相同的,因此实际的答案可能是,如果您不得不问这个问题,那么您的类太大了吗?
安迪

@DavidRodríguez-dribeas方法堆栈是什么意思?
committedandroider

@committedandroider:如果该值会超越当前函数调用
大卫·罗德里格斯- dribeas

46

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

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


21

我认为,仅当在调用之间使用数据时才需要实例变量。

这是一个例子:

myCircle = myDrawing.drawCircle(center, radius);

现在让我成像myDrawing类可以使用15个辅助函数来创建myCircle对象,并且每个函数都需要中心和半径。仍不应将它们设置为myDrawing类的实例变量。因为将不再需要它们。

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

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

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

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

至于公开一切。此刻可能会让您的生活更轻松。但这会再次困扰您。请不要。


您可以只定义move以使用参数(oldCenter,newCenter)。
obesechicken15年

4

恕我直言:

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

如果我发现自己反复将某些东西传递给实例的方法,或者发现我有大量的实例变量,我可能会尝试看一下我的设计,以防万一我错过了某些东西或在某个地方进行了错误的抽象。

希望能帮助到你


3

当然,在类中保留一大堆公共变量很容易。但是,即使从直觉上讲,您也可以说这不是路要走。

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

还考虑安全性,公共类变量容易受到“外部”代码的不必要更改。您的主要目标应该是使所有变量都私有,而没有的任何变量都应该有充分的理由。

关于将参数传递到堆栈的所有路径,这很快就会变得很丑陋。经验法则是使方法签名保持整洁优雅。如果您看到许多使用相同数据的方法,请确定对于成为类成员来说是否足够重要,如果不是,请对代码进行重构以使其更有意义。

归结为常识。仔细考虑一下在何处以及为何要声明每个新变量,其应具有的功能,然后从中决定应将其置于哪个范围。


您通常希望方法是公开的,因此可以对它们进行单元测试。
obesechicken15年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.