在PHP5中,使用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";

其他回答

$this->用于引用类的变量(成员变量)或方法的特定实例。

Example: 
$derek = new Person();

$derek现在是Person的一个特定实例。每个人都有一个first_name和一个last_name,但$derek有一个特定的first_name和last_name(derek Martin)。在$derek实例中,我们可以将它们称为$this->first_name和$this->last_name

ClassName::用于引用该类及其静态变量、静态方法。如果有帮助,你可以在心理上用“共享”代替“静态”一词。因为它们是共享的,所以它们不能引用$this,后者引用特定的实例(未共享)。静态变量(即静态$db_connection)可以在一类对象的所有实例之间共享。例如,所有数据库对象共享一个连接(静态$connection)。

静态变量示例:假设我们有一个具有单个成员变量的数据库类:static$num_connections;现在,将其放入构造函数中:

function __construct()
{
    if(!isset $num_connections || $num_connections==null)
    {
        $num_connections=0;
    }
    else
    {
        $num_connections++;
    }
}

就像对象有构造函数一样,它们也有析构函数,当对象死亡或未设置时执行析构函数:

function __destruct()
{
    $num_connections--;
}

每次创建新实例时,它都会将连接计数器增加一。每次我们销毁或停止使用实例时,都会将连接计数器减少一。通过这种方式,我们可以监视使用的数据库对象的实例数:

echo DB::num_connections;

因为$num_connections是静态的(共享的),所以它将反映活动数据库对象的总数。您可能已经看到这种技术用于在数据库类的所有实例之间共享数据库连接。这样做是因为创建数据库连接需要很长时间,所以最好只创建一个并共享它(这称为Singleton模式)。

静态方法(即,public Static View::format_phone_number($digits))可以在不首先实例化其中一个对象的情况下使用(即,它们不在内部引用$this)。

静态方法示例:

public static function prettyName($first_name, $last_name)
{
    echo ucfirst($first_name).' '.ucfirst($last_name);
}

echo Person::prettyName($derek->first_name, $derek->last_name);

如您所见,公共静态函数prettyName对对象一无所知。它只是处理传入的参数,就像不是对象一部分的普通函数。那么,如果我们可以不把它作为对象的一部分,那又何必麻烦呢?

首先,将函数附加到对象有助于保持事物的有序性,从而知道在哪里可以找到它们。第二,它可以防止命名冲突。在一个大型项目中,您可能需要两个开发人员创建getName()函数。如果一个创建ClassName1::getName(),另一个创建了ClassName2::getName(),则完全没有问题。没有冲突。是的静态方法!

自我::如果在具有要引用的静态方法的对象外部进行编码,则必须使用对象的名称View::format_phone_number($phone_number);如果在具有要引用的静态方法的对象内部进行编码,则可以使用对象的名称View::format_phone_number($pn),也可以使用self::format_prhone_number

静态变量也是如此:示例:View::templates_path与self::template_path

在DB类中,如果我们引用其他对象的静态方法,我们将使用对象的名称:示例:会话::getUsersOnline();

但如果DB类想要引用自己的静态变量,它只需要说self:示例:self::connection;

此外,由于$this::尚未讨论。

仅供参考,从PHP 5.3开始,当处理实例化对象以获取当前作用域值时,与使用static::不同,可以选择使用$this::这样。

http://ideone.com/7etRHy

class Foo
{
    const NAME = 'Foo';

    //Always Foo::NAME (Foo) due to self
    protected static $staticName = self::NAME;

    public function __construct()
    {
        echo $this::NAME;
    }

    public function getStaticName()
    {
       echo $this::$staticName;
    }
}

class Bar extends Foo
{
    const NAME = 'FooBar';

    /**
     * override getStaticName to output Bar::NAME
     */
    public function getStaticName()
    {
        $this::$staticName = $this::NAME;
        parent::getStaticName();
    }
}

$foo = new Foo; //outputs Foo
$bar = new Bar; //outputs FooBar
$foo->getStaticName(); //outputs Foo
$bar->getStaticName(); //outputs FooBar
$foo->getStaticName(); //outputs FooBar

使用上面的代码不是常见的或推荐的做法,只是为了说明它的用法,在引用原海报的问题时更像是“你知道吗?”。

它还表示$object::CONSTANT的用法,例如echo$foo::NAME;与$this::NAME相反;

情况1:使用self可以用于类常量

 class classA { 
     const FIXED_NUMBER = 4; 
     self::POUNDS_TO_KILOGRAMS
}

如果要在类外部调用它,请使用classA::POUNDS_to_KILOGAMS访问常量

情况2:对于静态财产

class classC {
     public function __construct() { 
     self::$_counter++; $this->num = self::$_counter;
   }
}

self(不是$self)指的是类的类型,而$this指的是该类的当前实例。self用于静态成员函数,允许您访问静态成员变量$这用于非静态成员函数,是对调用成员函数的类实例的引用。

因为这是一个对象,所以可以像这样使用它:$this->member

因为self不是一个对象,所以它基本上是一个自动引用当前类的类型。您可以像:self::member一样使用它

从这篇博客文章:

self指当前类self可用于调用静态函数和引用静态成员变量self可以在静态函数中使用self还可以通过绕过vtable来关闭多态行为$这是指当前对象$this可用于调用静态函数$this不应用于调用静态成员变量。改用self。$this不能在静态函数中使用