为什么PHP要求您明确写$this
?我会理解你是否必须在这里使用$this
:
function foo($bar) {
$this->bar = $bar;
}
但是你必须在看起来像这样的详细代码中明确地编写它:
$this->var3 = globalFun($this->var, $this->var2[$this->anotherVar], $this->method());
而不是:
$var3 = globaFun($var, $var2[$anotherVar], method());
那么$this
是什么意思?
为什么我们必须区分静态引用和实例?我们为什么需要:
static function getValue() {
return self::value;
}
如果有问题的变量/方法是静态的,PHP不能在运行时找到它吗?现在,如果我想将方法从静态更改为非静态,我必须将所有self::
替换为$this->
(反之亦然)。
如果我们的$this
表现得像Java一样,那会不会更好?
答案 0 :(得分:15)
由于重新开放,我会按照承诺在my answer张贴。
TL; DR版本如果不需要限定成员访问权限,则不仅会有性能损失,而且同一行代码可以同时表示字段访问和本地变量访问,取决于代码路径。
在PHP中,表中始终有一个符号表处于活动状态。这可以是全局符号表,也可以是函数/方法本地符号表(顺便说一句,它是由懒惰构建的)。除了编译变量之外的超全局和优化,当请求变量$var
时,它会在当前符号表中查找。由于对象属性不是存在于符号表中,而是存在于对象(实例属性)或与类关联的结构(静态属性)中,因此查找$var
永远不会返回属性。 / p>
要将给定变量带到函数范围,您必须通过创建引用来明确表示您的意图。例子:
$myglobal = 7;
class A {
private $prop;
public function meth() {
global $myglobal; //bring a global to the current scope
$prop =& $this->prop; //brings a property to the current scope
$local = 4;
$lambda = function () use (&$local) { };
}
}
显然,这只是一种更复杂的方式来表达当前发生的事情。问题是为什么会出现这种行为?
毕竟,在Java中,当有一个名为this.prop
的局部变量隐藏属性时,我们只需键入prop
。为什么这不是PHP的好选择?
我可以想到几个原因。
PHP有一种称为“动态属性”的东西。您可以在运行时为对象分配新属性。实际上,给定同一类的两个对象,一个可以具有给定属性$a
而另一个不具有给定属性。例如:
$obj1 = new stdClass();
$obj2 = new stdClass();
$obj1->a = 7;
不必声明变量;因此,根据代码路径,在某些时候可以定义变量,也可以不定义变量。为了增加对伤害的侮辱,我们还有一个名为“变量变量”的怪物。例如:
class A {
private $g = 3;
public function func($varname) {
if (rand(1,2) == 1) {
$g = 4; //no block scope; the scope is the function's
}
$$varname = 5; //god knows what's happening here
//if local variables hid properties, we'd have trouble
}
}
在Java中,给定标识符也可以在同一函数内表示局部变量和属性,但是:
由于这些事实,在编译时确定$var
是否引用了局部变量或属性是不可能的。因此:
答案 1 :(得分:14)
好的,让我们不再需要在任何地方写$this
。看看这种情况:
class Foo {
public function setBar($value) {
$bar = $value;
}
}
$foo = new Foo();
$foo->setBar('some value');
$bar
是局部变量还是$foo
的成员?
必须有一些区别。他们可以允许使用var
关键字声明局部变量,但这不会向后兼容,并且对于从旧版本的PHP升级的人来说会非常混乱。
同样的事情适用于self::
。解释器如何知道您要调用的函数是全局函数还是特定于该类的函数?
答案 2 :(得分:6)
PHP不是OOP。
现在是,但有副作用。
答案 3 :(得分:1)
实际上,我知道使用它的人。在Java中甚至在不必要的地方,因为他们觉得它创造了更清晰的代码;)我没有一个确定的答案,但我想,在内部,获得$ var总是必须转换为$ this-> var。因此,并不是因为强迫我们执行$ this-> var而故意让事情变得更复杂,而只是决定不实现$ var快捷方式。如果这有任何帮助,我不知道;)