class t {
public function tt()
{
echo 1;
}
}
t::tt();
看到了吗?非静态函数也可以在类级别调用。那么,如果我在
public
之前添加static
关键字,有什么不同呢?$this
,就像这样:class t {
protected $a = 10;
public function tt() {
echo $this->a;
echo 1;
}
}
t::tt();
当静态调用非静态方法时,您将会收到一个致命错误:
Fatal error: Using $this when not in object context in ...\temp.php on line 11
例如,你的示例有点过于简单,与实际情况不太相符;-)
还要注意,你的示例应该会收到严格警告(引用):
调用非静态方法静态地生成一个
E_STRICT
级别的警告。
实际上确实如此(至少在PHP 5.3中):
Strict Standards: Non-static method t::tt() should not be called statically in ...\temp.php on line 12
1
所以:不太好;-)
然而,静态调用非静态方法看起来并不像是任何一种良好的实践(这可能就是为什么它会引发一个严格警告的原因),因为静态方法和非静态方法没有相同的含义:静态方法不引用任何对象,而非静态方法在类的实例上工作。
再次强调:即使PHP允许您做某些事情(也许是出于历史原因——比如与旧版本的兼容性),也并不意味着您应该这样做!
E_ALL
不包括E_STRICT
- 参见http://www.php.net/manual/en/errorfunc.constants.php,该页面说明了在PHP < 6中,E_ALL
是“所有支持的错误和警告,但不包括严格级别(E_STRICT
)”。 - Pascal MARTINE_ALL & E_STRICT
,而是需要使用E_ALL | E_STRICT
(即您需要E_ALL
+ E_STRICT
),但我不确定在哪个版本的PHP中开始引发E_STRICT
。 - Pascal MARTINt::tt()
时,$this
将引用该对象,而没有任何警告。 - Tgr$this
**(即使通过实例对象调用)。只有当您尝试访问未定义的$this
时,才会收到致命错误。(您可以使用isset()
和empty()
测试其可用性。) - danorton由于静态方法可以在创建对象实例之前被调用,所以在声明为静态的方法内部,伪变量 $this 是不可用的。
不能使用箭头运算符 -> 通过对象访问静态属性。
以静态方式调用非静态方法会生成 E_STRICT 级别的警告。
仅仅因为你可以静态地调用非静态方法,并不意味着你应该这样做。这是一种不好的形式。
class A {
private static $counter = 0;
public function __construct() {
self::counter = self::counter + 1;
}
public function __destruct() {
self::counter = self::counter - 1;
}
public static function printCounter() {
echo "There are currently ".self::counter." instances of ".__CLASS__;
}
}
$a1 = new A();
$a2 = new A();
A::printCounter();
unset($a2);
A::printCounter();
PHP 5.3 引入了延迟静态绑定的概念,可以用于在静态继承的上下文中引用被调用的类。
是的,关键区别在于声明为static
的方法无法访问对象上下文变量$this
。
此外,在非对象上下文中调用非静态方法将触发E_STRICT
错误事件。当启用时,该事件的默认行为是向错误日志(或STDERR)输出消息,但它将允许程序继续运行。
此外,在非对象上下文中尝试引用$this
将触发E_ERROR
事件。该事件的行为是向错误日志(或STDERR)输出消息,并使用状态255退出程序。
例如:
<?php
error_reporting(-1);
//error_reporting(E_ALL);
class DualNature {
public static function fnStatic() {
if ( isset( $this ) ) {
// never ever gets here
$myValue = $this->_instanceValue;
} else {
// always gets here
$myValue = self::$_staticValue;
}
return $myValue;
}
public function fnInstance() {
if ( isset( $this ) ) {
// gets here on instance (->) reference only
$myValue = $this->_instanceValue;
} else {
// gets here in all other situations
$myValue = self::$_staticValue;
}
return $myValue;
}
public static function fnStaticDeath() {
return $this->_instanceValue;
}
private static $_staticValue = 'no access to $this';
private $_instanceValue = '$this is available';
}
$thing = new DualNature();
echo "==========\n";
printf("DualNature::fnStatic(): \"%s\"\n", DualNature::fnStatic() );
echo "==========\n";
printf("\$thing::fnStatic(): \"%s\"\n", $thing::fnStatic() );
echo "==========\n";
printf("\$thing->fnStatic(): \"%s\"\n", $thing->fnStatic() );
echo "==========\n";
printf("DualNature::fnInstance(): \"%s\"\n", DualNature::fnInstance() );
echo "==========\n";
printf("\$thing::fnInstance(): \"%s\"\n", $thing::fnInstance() );
echo "==========\n";
printf("\$thing->fnInstance(): \"%s\"\n", $thing->fnInstance() );
echo "==========\n";
printf("\$thing->fnStaticDeath(): \"%s\"\n", $thing->fnStaticDeath() );
echo "==========\n";
echo "I'M ALIVE!!!\n";
==========
PHP Strict Standards: Non-static method DualNature::fnInstance() should not be called statically in example.php on line 45
DualNature::fnStatic(): "no access to $this"
==========
$thing::fnStatic(): "no access to $this"
==========
$thing->fnStatic(): "no access to $this"
PHP Strict Standards: Non-static method DualNature::fnInstance() should not be called statically in example.php on line 47
==========
DualNature::fnInstance(): "no access to $this"
==========
$thing::fnInstance(): "no access to $this"
==========
$thing->fnInstance(): "$this is available"
==========
PHP Fatal error: Using $this when not in object context in example.php on line 29
E_ALL
将抑制默认的E_STRICT
警告消息(事件仍将传播),但对$this
的无效引用仍将导致致命错误并退出程序。