参数与成员变量
Posted
技术标签:
【中文标题】参数与成员变量【英文标题】:Parameter vs. Member variables 【发布时间】:2010-10-06 11:41:57 【问题描述】:我最近一直在处理其他人的代码,我意识到这个人在私有变量和方法参数方面的理念与我截然不同。我通常认为私有变量应该只在以下情况下使用:
-
需要存储变量以供以后调用。
存储在变量中的数据在类中全局使用。
当需要对变量进行全局操作时(这与每个类方法读取变量的需要截然不同)。
什么时候它会使编程变得更加容易。 (诚然含糊不清,但在许多情况下必须避免将自己逼入角落)。
(我承认,以上许多内容略有重复,但它们似乎各自不同,足以值得这样处理......) 这似乎是防止意外更改变量的最有效方法。似乎遵循这些标准将允许最终操纵外部引用(如果最终修改了类),从而为您在未来留下更多选择。这仅仅是一个风格问题(就像一个真正的括号或匈牙利命名约定),还是我有理由相信这种信念?在这种情况下实际上有最佳实践吗?
编辑 我认为这需要纠正。我在上面的实际意思是“全局地通过实例方法”而不是“任何地方、任何地方都可以全局访问”。edit2 要求提供一个示例:
class foo
private $_my_private_variable;
public function __constructor__()
public function useFoo( $variable )
// This is the line I am wondering about,
// there does not seem to be a need for storing it.
$this->_my_private_variable = $variable;
$this->_doSometing();
private function _doSomething()
/*
do something with $this->_my_private_variable.
*/
// This is the only place _my_private_variable is used.
echo $this->_my_private_variable;
这就是我会做的方式:
class foo
public function __constructor__()
public function useFoo( $variable )
$this->_doSometing( $variable );
private function _doSomething( $passed_variable )
/*
do something with the parameter.
*/
echo $passed_variable;
【问题讨论】:
嗯,那他在做什么呢?要求在调用方法之前设置对象数据,其中所述数据仅在该方法中使用并且仅与单个调用相关?如果是这样,是的 - 那太愚蠢了。如果不是,请澄清! 好吧,所有数据都以某种方式正确设置。例如,在某个地方,信息是在构造函数中定义的,但它可以(同样容易地)作为参数传递。 他的使用似乎并不完全是荒谬的,但它似乎与最佳实践相去甚远。 请给出相关代码的具体例子。 【参考方案1】:如果您熟悉 C++ 析构函数,我认为答案很简单。所有成员变量都应该被分配一种被破坏的方式,而函数参数则不是。这就是为什么成员变量通常是对象的状态或依赖项,它们与它们的生命周期有某种关系。
【讨论】:
【参考方案2】:类成员应该是以下任何一种:
类的依赖项 表示类状态的变量 类的方法【讨论】:
【参考方案3】:由于对象属性是用来保存状态的,正如其他人所说,我的策略是默认将它们全部设为私有,除非我有充分的理由公开它们。
如果必须的话,稍后将它们公开要容易得多,只需编写一个 getter 方法(我也不必在开始编写类时就考虑它)。但是稍后卷入公共财产可能需要重写大量代码。
我喜欢保持灵活性,而不必考虑超出需要的范围。
【讨论】:
【参考方案4】:一般来说,类成员应该代表类对象的状态。
它们不是方法参数的临时位置(这就是方法参数的用途)。
【讨论】:
类对象的状态 - 或 - 类对象的依赖项 我认为如果都是私有状态就可以了。减少一些频繁使用的参数可以使代码更易于阅读。 @byxor 但它也会立即使您的类成为非线程安全的 非常正确。我们很快就会离开单线程世界,所以这是非常重要的一点。【参考方案5】:我不同意实现它以实现全局访问或使编程更容易。通过在不进行任何过滤的情况下在全球范围内公开这些内容,使确定未来的访问变得更加困难。
【讨论】:
【参考方案6】:我不确定使用全局范围的变量与始终作为方法参数传递是否有明确的最佳实践。 (通过“私有变量”,我假设您的意思是全局范围的变量。)
使用全局范围的变量是在 .NET 中实现属性的唯一方法(即使是自动属性最终也使用全局范围的变量,而不是您必须自己声明的变量)。
始终使用方法参数存在争议,因为它可以完全清楚值的来源。我不认为它真的有助于阻止该方法对基础值进行更改,而且在我看来,它有时会使事情变得更难阅读。
【讨论】:
【参考方案7】:拥有一个成员变量意味着它将保持需要在方法调用之间保持的状态。如果值不需要在调用之间存在,则它没有理由存在于单个调用的范围之外,因此(如果它存在的话)应该是方法本身中的一个变量。
风格总是很难,一旦你开发了一种风格,你可能会陷入一些陈规之中,并且很难理解为什么你所做的可能不是最好的方式。
【讨论】:
【参考方案8】:我声称这不是风格问题,而是可读性/可维护性问题。一个变量应该有一种用途,而且只有一种用途。仅仅因为它们碰巧需要相同的类型而为不同的目的“回收”变量是没有任何意义的。
从您的描述看来,您处理的其他人的代码似乎就是这样做的,因为所有其他用途基本上都包含在您的列表中。简而言之,它根据情况使用私有成员变量充当临时变量。我可以这样假设吗?如果是这样,代码太可怕了。
任何给定变量的词法范围和生命周期越小,错误使用的可能性越小,对资源的处理就越好。
【讨论】:
非常感谢。我是这么想的。 喜欢你的最后一段。但是,就性能而言,将变量回收为临时缓冲区不会降低 alloc/free 的成本吗?此外,当链接多个方法调用时,将值压入对象并在最终调用时弹出它更具可读性,而不是将其作为参数一直传递。无论如何,即使不一定是最佳实践,您能否解释一下为什么您认为这段代码“可怕”? @yO_ 在 php 中,由于 alloc/free 造成的性能差异几乎可以肯定非常小,以至于无法测量。无论如何,如此微小的微优化永远无法证明编写可维护性较差的代码是合理的。方法链是一个非常不同的情况:在这里,您正在设置对象的逻辑状态并随后对其进行操作,因此使用私有成员非常有意义。 OP 明确排除了这种情况。【参考方案9】:您应该只在需要的时间和地点创建变量,并在完成后处理它们。如果该类不需要类级变量来运行,那么它就不需要一个。在不需要的地方创建变量是非常糟糕的做法。
【讨论】:
您是否鼓励人们内联所有内容,因为代码运行并不总是需要变量?以上是关于参数与成员变量的主要内容,如果未能解决你的问题,请参考以下文章
C++类里成员变量为什么加前缀m_?(避免成员变量与传入参数名称冲突)