这可能是一个基本问题,但它让我想了很长时间。
我应该声明所有私有/本地变量是私有的吗?或者这只是“重要”变量所必需的?
例如,我有(临时)计算结果。我应该预先声明这个变量吗?
希望有人可以指出这一点。
答案 0 :(得分:8)
由于您正在谈论private
,protected
和public
,我认为您正在谈论属性,而不是变量。
在这种情况下:是,你应事先声明它们。
由于PHP对象的设计方式,在编译时会创建一个数组(properties_table
)。此数组确保尽可能快地访问给定属性。但是,如果随着时间的推移添加属性,PHP也需要跟踪这一点。因此,对象也有一个简单的properties
表
而第一个(properties_table
)是一个指针数组,而后者是一个简单的键=>价值表。
所以呢?好吧,因为properties_table
只包含指针(具有固定大小),所以它们存储在一个简单的数组中,并使用各自的偏移量来获取指针。偏移量存储在另一个HashTable中,which is the ce->properties_info
pointer。
正如bwoebi在评论中指出的那样:获取偏移量(HashTable查找)是最坏情况的线性操作(O(n)),预定义属性查找是常数时间复杂操作(O(1))。另一方面,动态属性需要另一个HashTable查找,最坏情况下的线性操作(O(n))。这意味着,访问动态属性平均需要大约两倍的时间。维基百科的作者可以explain Time-Complexity比我更好。
首先,访问修饰符似乎无关紧要。随着你的进展,你很快就会发现,有时候,你只是不想冒某些对象的某些属性被某些代码修改的机会。当你看到private
的价值时
如果一个对象包含另一个对象,该对象包含您的代码所依赖的各种设置,例如,您可能会使用getter方法从外部访问这些设置,但是您可以将该实际属性隐藏起来使用private
。
如果进一步下行,您将要为项目添加数据模型和服务层,那么您将编写一个(抽象)父类,如果仅用于类型提示,则会有一个很好的更改。 />
如果这些服务实例包含类似于配置属性的东西,您可能会在父类中定义该getter(仅定义一次)。 private
表示仅当前类可以访问属性,但由于您不打算使用父项的实例,而是该子项的实例,在处理大型项目时,我会明白为什么protected
非常宝贵。
就临时变量而言,无论是在方法,函数还是其他任何地方,你都没有 预先声明它们,除非在某些情况下阵列:
public function foo()
{
$temp = $this->getSomeValue();
return $temp ? $temp +1 : null;
}
完全有效,如果你要写
,就不会有更好的效果public function foo()
{
$temp;// or $temp = null;
$temp = $this->getSomeValue();
return $temp ? $temp +1 : null;
}
然而,看到像这样的东西并不罕见:
public function bar($length = 1)
{
for ($i=0;$i<$length;$i++)
{
$return[] = rand($i+1, $length*10);
}
return $return;
}
此代码依赖于PHP足以创建数组,并在达到$return
语句时将其分配给$return[] = rand();
。 PHP会这样做,但是将你的ini设置为E_STRICT | E_ALL
会显示它没有抱怨它就不会这样做。将0
传递给方法时,将不会创建数组,并且当PHP到达return $return;
语句时,它也会抱怨:未声明的变量。它不仅麻烦,而且还会减慢你的速度!最好将$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;
}
为了安全起见,我还要检查参数类型:
/**
* 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;
}
答案 1 :(得分:3)
在大多数情况下(如果不是全部):是。
如果变量是类属性,则绝对应该在使用前声明。
如果变量是函数的局部变量,请在使用之前在该函数中声明它。函数变量仅限于函数的作用域(局部变量)。他们在使用前没有有声明,但这样做是好的做法,如果你这样做,它就会消除警告信息。如果它们没有在其他任何地方使用,那么它们不应该属于
答案 2 :(得分:2)
如果您在全班的上下文中使用它,那么是,您应该将您的变量定义为该类的成员。
但是,如果您在单个函数的上下文中讨论局部变量并且该变量不需要在别处使用(或者不返回),那么不。
基本上,您需要在决定是否将其作为类属性之前确定变量的重要性和范围。
例如:
<?php
class Test {
private $test; // Private property, for use in the class only
public $public_test; // Public Property, for use both internally and external to the class as a whole
public function testing() {
$local = 5; // Local variable, not needed outside of this function ever
$this->test = rand(1, 5);
$calc = $local * $this->test; // Local variable, not needed outside of this function ever
$this->public_test = $calc / 2; // The only thing that the whole class, or public use cares about, is the result of the calculation divided by 2
}
}
答案 3 :(得分:1)
变量在使用前定义和初始化通常是一个很好的经验法则。这不仅包括定义和初始值,还包括输入值的验证和过滤,以便在具体处理这些变量包含的数据之前建立一大块代码所基于的所有前提条件。
同样自然适用于对象成员(属性),因为它们是整个对象的变量。所以它们应该已经在类中定义(默认情况下它们的值在PHP中为NULL
)。动态值/过滤可以在构造函数和/或setter方法中完成。
可见性规则类似于代码中的任何规则:尽可能少(很难实现的简单规则)。所以保持本地,然后私有 - 取决于它是函数变量还是对象属性。
也许保持在脑海中,在PHP中,您可以从同一个类中访问私有属性 - 不仅仅是同一个对象。这可能很有用,因为它可以让你把事情保密一点。
例如,我有(临时)计算结果。我应该预先声明这个变量吗?
这通常是函数或方法中的局部变量。它在接收计算方法的返回值时定义。所以没有必要预先声明它(本身)。
...
function hasCalculation() {
$temp = $this->calculate();
return (bool) $temp;
}
...
如果计算是昂贵的,那么存储(缓存)值可能是有意义的。当你封装它时,例如在一个对象中,这很容易。在这种情况下,您将使用私有属性在计算后存储该值。
这些规则带有一丝盐,它们用于一般方向,你可以很容易地从中进行修改,所以这是可以扩展的,所以这是保持灵活性的好方法。