PHP中的静态方法与非静态方法有什么区别吗?

时间:2010-03-13 16:22:44

标签: php static public

class t {
    public function tt()
    {
        echo 1;
    }
}
t::tt();

参见?非静态函数也可以在类级别调用。如果我在static之前添加public关键字有什么不同?

6 个答案:

答案 0 :(得分:15)

除此之外,如果您尝试在方法中使用$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

即。你的例子有点太简单,并不真实对应于真实案例; - )


另请注意,您的示例应该向您发出严格警告(quoting):

  

静态调用非静态方法   生成E_STRICT级警告。

它实际上是(至少,使用PHP 5.3)

Strict Standards: Non-static method t::tt() should not be called statically in ...\temp.php on line 12
1

所以:不那么好; - )


尽管如此,静态调用非静态方法并不像任何一种良好的实践(这可能是它提出严格警告的原因),因为静态方法与非静态方法的意义不同-static:静态方法不引用任何对象,而非静态方法则用于调用类的实例。


再一次:即使PHP允许你做某些事情(也许是出于历史原因 - 比如与旧版本的兼容性),这并不意味着你应该这样做!

答案 1 :(得分:4)

Static Keyword

  

因为静态方法在没有创建对象实例的情况下是可调用的,所以伪变量$ this在声明为static的方法中不可用。

     

使用箭头操作符 - >。

无法通过对象访问静态属性      

静态调用非静态方法会生成E_STRICT级别警告。

仅仅因为你可以静态地调用非静态方法并不意味着你应该这样做。这是糟糕的形式。

答案 2 :(得分:2)

通常,静态方法也称为类方法,而非静态方法也称为对象方法实例方法。 / p>

类方法和对象方法之间的区别在于类方法只能访问类属性(静态属性),而对象方法用于访问对象属性(同一个类实例的属性)。

静态方法和属性用于在特定类的所有实例上共享公共数据。

例如,您可以使用静态属性来跟踪实例数:

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();

请注意,静态属性计数器是私有的,因此只能由类本身和该类的实例访问,但不能从外部访问。

答案 3 :(得分:1)

未提及的主要差异与 多态行为 有关。

非静态方法在派生类中重新声明时,会覆盖基类方法,并根据调用它们的实例类型允许多态行为。 静态方法不是这种情况


PHP 5.3引入了late static binding的概念,可用于在静态继承的上下文中引用被调用的类。

答案 4 :(得分:0)

是的,关键的区别在于声明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的无效引用仍会导致致命错误并将退出该计划。

答案 5 :(得分:0)

除了语法和功能差异之外,还有一个重要的性能差异。

您可以参考这个或多或少详细的comparison of static and non-static methods in PHP