在PHP5中,使用self和$this有什么区别?

什么时候合适?


当前回答

$this指当前类对象,self指当前类(Not对象)。类是对象的蓝图。所以你定义了一个类,但是你构造了对象。

换句话说,对静态成员或方法使用self,而对非静态成员和方法使用this。

同样在子/父场景中,self/parent主要用于标识子和父类成员和方法。

其他回答

根据静态关键字,没有任何$self。只有$this用于引用类(对象)的当前实例,self用于引用类的静态成员。对象实例和类之间的区别在这里发挥作用。

关键字self不仅仅指“当前类”,至少不会限制静态成员。在非静态成员的上下文中,self还提供了一种绕过当前对象的vtable(参见vtable上的wiki)的方法。正如您可以使用parent::methodName()调用函数的父版本一样,您也可以调用self::methodName)调用方法的当前类实现。

class Person {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }

    public function getTitle() {
        return $this->getName()." the person";
    }

    public function sayHello() {
        echo "Hello, I'm ".$this->getTitle()."<br/>";
    }

    public function sayGoodbye() {
        echo "Goodbye from ".self::getTitle()."<br/>";
    }
}

class Geek extends Person {
    public function __construct($name) {
        parent::__construct($name);
    }

    public function getTitle() {
        return $this->getName()." the geek";
    }
}

$geekObj = new Geek("Ludwig");
$geekObj->sayHello();
$geekObj->sayGoodbye();

这将输出:

你好,我是极客路德维希路德维希再见了

sayHello()使用$this指针,因此调用vtable调用Geek::getTitle()。sayGoodbye()使用self::getTitle(),因此不使用vtable,而是调用Person::getTitle()。在这两种情况下,我们都在处理实例化对象的方法,并且可以访问调用函数中的$this指针。

当self与::运算符一起使用时,它引用当前类,这可以在静态和非静态上下文中完成$这是指对象本身。此外,使用$this调用静态方法(但不引用字段)是完全合法的。

这里有一个小的基准(第7.2.24节):

            Speed (in seconds)  Percentage
$this->     0.91760206222534    100
self::      1.0047659873962     109.49909865716
static::    0.98066782951355    106.87288857386

4000 000次运行的结果。结论:没关系。这是我使用的代码:

<?php

class Foo
{
  public function calling_this() { $this->called(); }
  public function calling_self() { self::called(); }
  public function calling_static() { static::called(); }
  public static function called() {}
}

$foo = new Foo();
$n = 4000000;
$times = [];

// warmup
for ($i = 0; $i < $n; $i++) { $foo->calling_this(); }
for ($i = 0; $i < $n; $i++) { $foo->calling_self(); }
for ($i = 0; $i < $n; $i++) { $foo->calling_static(); }

$start = microtime(true);
for ($i = 0; $i < $n; $i++) { $foo->calling_this(); }
$times["this"] = microtime(true)-$start;

$start = microtime(true);
for ($i = 0; $i < $n; $i++) { $foo->calling_self(); }
$times["self"] = microtime(true)-$start;

$start = microtime(true);
for ($i = 0; $i < $n; $i++) { $foo->calling_static(); }
$times["static"] = microtime(true)-$start;

$min = min($times);
echo $times["this"] . "\t" . ($times["this"] / $min)*100 . "\n";
echo $times["self"] . "\t" . ($times["self"] / $min)*100 . "\n";
echo $times["static"] . "\t" . ($times["static"] / $min)*100 . "\n";

如果您想调用类的方法而不创建该类的对象/实例,则使用self,从而节省RAM(有时使用self)。换句话说,它实际上是在静态地调用一个方法。将其用于对象透视。