这可能是一个基本问题,但它让我想了很长一段时间.
我应该声明所有私有/本地变量是私有的吗?或者这只是"重要"变量的必要条件?
例如,我有(临时)计算结果.我应该预先声明这个变量吗?
希望有人可以指出这一点.
既然你是在谈论private,protected而且public我想你所谈论的性质,而不是变量.
在这种情况下:是的,您应该事先声明它们.
由于PHP对象的设计方式,properties_table因此在编译时会创建一个array().此数组确保尽可能快地访问给定属性.但是,如果随着时间的推移添加属性,PHP也需要跟踪这一点.因此,对象也有一个简单的properties表.
而first(properties_table)是一个指针数组,而后者是一个简单的key => value表.
所以呢?好吧,因为properties_table它只包含指针(具有固定大小),所以它们存储在一个简单的数组中,并使用它们各自的偏移量来获取指针.偏移量存储在另一个HashTable中,它是ce->properties_info指针.
正如bwoebi在评论中指出的那样:获得偏移量(HashTable查找)是最坏情况的线性操作(O(n)),预定义属性查找是常数时间复杂操作(O(1)).另一方面,动态属性需要另一个HashTable查找,最坏情况下的线性操作(O(n)).这意味着,访问动态属性平均需要大约两倍的时间.维基百科的作者可以比我更好地解释时间复杂性.
首先,访问修饰符似乎无关紧要.随着你的进展,你很快就会发现,有时候,你只是不想冒某些对象的某些属性被某些代码修改的机会.那是你看到的价值private.
如果一个对象包含另一个对象,该对象包含您的代码所依赖的各种设置,例如,您可能会使用getter方法从外部访问这些设置,但是您可以将该实际属性隐藏起来使用private.
如果,更进一步,您将要为项目添加数据模型和服务层,那么您将编写一个(抽象)父类,如果仅用于类型提示,则会有一个很好的更改.
如果这些服务实例包含类似于配置属性的东西,您可能会在父类中定义该getter(仅定义一次).private意味着只有当前类可以访问属性,但由于您不打算使用父项的实例,而是子项的实例,因此您将看到为什么protected在处理大型项目时具有无法估量的价值,太.
至于临时变量而言,无论是在方法,函数或其他地方,你不会有要预先声明他们,除了在某些情况下数组:
public function foo()
{
$temp = $this->getSomeValue();
return $temp ? $temp +1 : null;
}
Run Code Online (Sandbox Code Playgroud)
是完全有效的,如果你写的话也不会更好
public function foo()
{
$temp;// or $temp = null;
$temp = $this->getSomeValue();
return $temp ? $temp +1 : null;
}
Run Code Online (Sandbox Code Playgroud)
但是,看到像这样的东西并不罕见:
public function bar($length = 1)
{
for ($i=0;$i<$length;$i++)
{
$return[] = rand($i+1, $length*10);
}
return $return;
}
Run Code Online (Sandbox Code Playgroud)
此代码依赖于PHP足以创建数组,并$return在到达$return[] = rand();语句时将其分配给它.PHP会这样做,但设置你的ini E_STRICT | E_ALL会显示它没有抱怨而不会这样做.传递0给方法时,将不会创建数组,并且PHP在到达return $return;语句时也会抱怨:undeclared变量.它不仅麻烦,而且还会减慢你的速度!最好$return在范围顶部声明为数组:
public function bar($length = 1)
{
$return = array();//that's it
for ($i=0;$i<$length;$i++)
{
$return[] = rand($i+1, $length*10);
}
return $return;
}
Run Code Online (Sandbox Code Playgroud)
为了安全起见,我还要检查参数类型:
/**
* construct an array with random values
* @param int $length = 1
* @return array
**/
public function bar($length = 1)
{
$length = (int) ((int) $length > 0 ? $length : 1);//make length > 0
$return = array();
for ($i=0;$i<$length;$i++)
{
$return[] = rand($i+1, $length*10);
}
return $return;
}
Run Code Online (Sandbox Code Playgroud)
对于变量来说,在使用之前定义和初始化它们通常是一个很好的经验法则。这不仅包括定义和初始值,还包括输入值的验证和过滤,以便在对这些变量包含的数据进行具体处理之前建立代码块所基于的所有前提条件。
这同样自然地适用于对象成员(属性),因为它们是整个对象的变量。所以它们应该已经在类中定义(默认情况下它们的值NULL在 PHP 中)。动态值/过滤可以在构造函数和/或设置方法中完成。
可见性规则类似于代码中的任何规则:尽可能少(简单的规则很难实现)。因此,先保留本地内容,然后再保留私有内容 - 取决于它是函数变量还是对象属性。
也许请记住,在 PHP 中,您可以从同一个类中访问私有属性,而不仅仅是同一个对象。了解这一点很有用,因为它可以让您将事情保密的时间更长一些。
例如,我有计算的(临时)结果。我应该预先声明这个变量吗?
这通常是函数或方法中的局部变量。它是在接收到计算方法的返回值时定义的。因此无需预先声明它(本身)。
...
function hasCalculation() {
$temp = $this->calculate();
return (bool) $temp;
}
...
Run Code Online (Sandbox Code Playgroud)
如果计算成本很高,那么存储(缓存)该值可能是有意义的。当您将其封装在例如对象中时,这很容易实现。在这种情况下,您将使用私有属性来存储计算后的值。
对这些规则持保留态度,它们是针对一般方向的,您可以轻松地从中进行修改,因此这是开放扩展的,因此是保持灵活性的好方法。