关于php:什么时候使用self 和$this?

When to use self over $this?

在php 5中,使用self$this有什么区别?

什么时候合适?


短的答案

Use $this to refer to the current
object. Use self to refer to the
current class. In other words, use
$this->member for non-static members,
use self::$member for static members.

完整的答案

这里是一个例子的正确使用和self$this大学非营利的静态和静态成员变量:

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
class X {
    private $non_static_member = 1;
    private static $static_member = 2;

    function __construct() {
        echo $this->non_static_member . ' '
           . self::$static_member;
    }
}

new X();
?>

这里是一个例子,不使用$this大学和非营利self静态和静态成员变量:

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
class X {
    private $non_static_member = 1;
    private static $static_member = 2;

    function __construct() {
        echo self::$non_static_member . ' '
           . $this->static_member;
    }
}

new X();
?>

这里是一个例子$this在学院中的成员函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
class X {
    function foo() {
        echo 'X::foo()';
    }

    function bar() {
        $this->foo();
    }
}

class Y extends X {
    function foo() {
        echo 'Y::foo()';
    }
}

$x = new Y();
$x->bar();
?>

这里是一个例子所使用的多态性行为及self成员函数为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
class X {
    function foo() {
        echo 'X::foo()';
    }

    function bar() {
        self::foo();
    }
}

class Y extends X {
    function foo() {
        echo 'Y::foo()';
    }
}

$x = new Y();
$x->bar();
?>

The idea is that $this->foo() calls the foo() member function of whatever is the exact type of the current object. If the object is of type X, it thus calls X::foo(). If the object is of type Y, it calls Y::foo(). But with self::foo(), X::foo() is always called.

从http:/ / / / www.phpbuilder.com板允许吗?10354489:T =

通过http:/ / / member.php board.phpbuilder.com?145249 -激光


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
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();

这将输出:

Hello, I'm Ludwig the geek
Goodbye from Ludwig the person

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


不使用self::,使用static::

自我还有另一个方面:值得一提。恼人的是,self::是指定义点的范围,而不是执行点的范围。用两种方法来考虑这个简单类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Person
{

    public static function status()
    {
        self::getStatus();
    }

    protected static function getStatus()
    {
        echo"Person is alive";
    }

}

如果我们称之为Person::status(),我们会看到"人还活着"。现在考虑当我们创建一个继承自此的类时会发生什么:

1
2
3
4
5
6
7
8
9
class Deceased extends Person
{

    protected static function getStatus()
    {
        echo"Person is deceased";
    }

}

调用Deceased::status()时,我们希望看到"人已死亡",但我们看到的是"人还活着",因为定义了对self::getStatus()的调用时,作用域包含原始方法定义。

php 5.3有一个解决方案。static::解析运算符实现了"后期静态绑定",这是一种奇特的说法,即它绑定到所调用类的范围。把status()中的行改为static::getStatus()中的行,结果就是您所期望的。在旧版本的PHP中,您必须找到一个Kludge才能做到这一点。

参见PHP文档

所以回答这个问题,而不是按要求…

$this->表示当前对象(类的实例),而static::表示类


为了真正理解我们在讨论self$this时所说的话,我们需要从概念和实践层面深入探讨正在发生的事情。我真的觉得这些答案都做得不合适,所以下面是我的尝试。好的。

让我们从讨论什么是类和对象开始。好的。概念上的类和对象

那么,什么是班级?很多人把它定义为对象的蓝图或模板。实际上,您可以在这里了解更多关于PHP类的信息。在某种程度上,这才是真正的。让我们看一个类:好的。

1
2
3
4
5
6
class Person {
    public $name = 'my name';
    public function sayHello() {
        echo"Hello";
    }
}

如您所知,该类上有一个名为$name的属性和一个名为sayHello()的方法(函数)。好的。

需要注意的是,类是一个静态结构。这意味着类Person一旦定义,在任何地方都是相同的。好的。

另一方面,对象被称为类的实例。这意味着我们获取类的"蓝图",并使用它来创建动态副本。这个副本现在专门绑定到它存储的变量。因此,对实例的任何更改都是该实例的本地更改。好的。

1
2
3
4
$bob = new Person;
$adam = new Person;
$bob->name = 'Bob';
echo $adam->name; //"my name"

我们使用new操作符创建类的新实例。好的。

因此,我们说类是全局结构,对象是局部结构。不要担心有趣的->语法,我们将在一点内讨论它。好的。

另一件我们应该讨论的事情是,我们可以检查一个实例是否是一个instanceof特定类:$bob instanceof Person,如果$bob实例是使用Person类或Person的子类生成的,则返回一个布尔值。好的。定义状态

所以让我们来深入研究一下类实际包含的内容。一个类包含5种类型的"东西":好的。

  • 属性-将这些视为每个实例将包含的变量。好的。

    1
    2
    3
    class Foo {
        public $bar = 1;
    }
  • 静态属性-将这些属性视为在类级别共享的变量。这意味着它们不会被每个实例复制。好的。

    1
    2
    3
    class Foo {
        public static $bar = 1;
    }
  • 方法-这些是每个实例将包含的函数(并对实例进行操作)。好的。

    1
    2
    3
    class Foo {
        public function bar() {}
    }
  • 静态方法-这些是在整个类中共享的函数。它们不在实例上操作,而是只在静态属性上操作。好的。

    1
    2
    3
    class Foo {
        public static function bar() {}
    }
  • 常量-类解析的常量。这里不再深入,但为了完整性增加了:好的。

    1
    2
    3
    class Foo {
        const BAR = 1;
    }
  • 因此,基本上,我们使用关于静态的"提示"来存储类和对象容器上的信息,这些提示标识信息是否共享(因此是静态的)或者不共享(因此是动态的)。好的。状态和方法

    在方法内部,对象的实例由$this变量表示。该对象的当前状态在那里,任何属性的变化(更改)都将导致对该实例的更改(而不是其他实例)。好的。

    如果静态调用方法,则不定义$this变量。这是因为没有与静态调用关联的实例。好的。

    有趣的是静态调用是如何进行的。那么让我们来谈谈我们如何访问这个州:好的。访问状态

    所以现在我们已经存储了这个状态,我们需要访问它。这可能会变得有点棘手(或者说有点复杂),所以让我们将其分为两种观点:从实例/类外部(比如从普通函数调用或全局范围)和实例/类内部(从对象上的方法内部)。好的。从实例/类外部

    从实例/类的外部来看,我们的规则非常简单和可预测。我们有两个操作符,如果我们处理的是实例或类静态的,每个操作符都会立即告诉我们:好的。

    • ->-对象操作符-当我们访问一个实例时,总是使用它。好的。

      1
      2
      $bob = new Person;
      echo $bob->name;

      需要注意的是,调用Person->foo是没有意义的(因为Person是一个类,而不是一个实例)。因此,这是一个分析错误。好的。

    • ::—作用域解析操作符—它总是用于访问类静态属性或方法。好的。

      1
      echo Foo::bar()

      此外,我们可以用同样的方法对对象调用静态方法:好的。

      1
      echo $foo::bar()

      需要特别注意的是,当我们从外部执行此操作时,对象的实例隐藏在bar()方法中。这意味着它与跑步完全相同:好的。

      1
      2
      $class = get_class($foo);
      $class::bar();

    因此,静态调用中没有定义$this。好的。从实例/类内部

    这里的情况有点变化。使用相同的运算符,但它们的含义变得明显模糊。好的。

    对象运算符->仍用于调用对象的实例状态。好的。

    1
    2
    3
    4
    5
    6
    class Foo {
        public $a = 1;
        public function bar() {
            return $this->a;
        }
    }

    使用对象操作符:$foo->bar()$foo上调用bar()方法(Foo的一个实例),将导致该实例的$a版本。好的。

    所以这就是我们所期望的。好的。

    ::运算符的含义虽然有所改变。它取决于对当前函数的调用的上下文:好的。

    • 在静态上下文中好的。

      在静态上下文中,使用::进行的任何调用也将是静态的。让我们来看一个例子:好的。

      1
      2
      3
      4
      5
      6
      7
      8
      class Foo {
          public function bar() {
              return Foo::baz();
          }
          public function baz() {
              return isset($this);
          }
      }

      调用Foo::bar()将静态调用baz()方法,因此不会填充$this。值得注意的是,在最新版本的php(5.3+)中,这将触发E_STRICT错误,因为我们静态地调用非静态方法。好的。

    • 在实例上下文中好的。

      另一方面,在实例上下文中,使用::进行的调用依赖于调用的接收者(我们调用的方法)。如果方法被定义为static,那么它将使用静态调用。如果不是,它将转发实例信息。好的。

      因此,看看上面的代码,调用$foo->bar()将返回true,因为"静态"调用发生在实例上下文中。好的。

    有道理?我不这么认为。这让人困惑。好的。快捷关键词

    因为使用类名将所有东西捆绑在一起是相当脏的,所以PHP提供了3个基本的"快捷键"关键字以使范围解析更容易。好的。

    • self—指当前的类名。因此,self::baz()Foo类内的Foo::baz()相同(任何方法)。好的。

    • parent—指当前类的父类。好的。

    • static—这是指被调用的类。由于继承,子类可以重写方法和静态属性。因此,使用static而不是类名来调用它们可以让我们解析调用的来源,而不是当前级别。好的。

    实例

    要理解这一点,最简单的方法是从一些例子开始。让我们选一个班级:好的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    class Person {
        public static $number = 0;
        public $id = 0;
        public function __construct() {
            self::$number++;
            $this->id = self::$number;
        }
        public $name ="";
        public function getName() {
            return $this->name;
        }
        public function getId() {
            return $this->id;
        }
    }

    class Child extends Person {
        public $age = 0;
        public function __construct($age) {
            $this->age = $age;
            parent::__construct();
        }
        public function getName() {
            return 'child: ' . parent::getName();
        }
    }

    现在,我们也在研究遗产。暂时忽略这是一个坏的对象模型,但让我们看看当我们使用它时会发生什么:好的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    $bob = new Person;
    $bob->name ="Bob";
    $adam = new Person;
    $adam->name ="Adam";
    $billy = new Child;
    $billy->name ="Billy";
    var_dump($bob->getId()); // 1
    var_dump($adam->getId()); // 2
    var_dump($billy->getId()); // 3

    所以ID计数器在两个实例和子实例之间共享(因为我们使用self)来访问它。如果我们使用static,我们可以在子类中重写它)。好的。

    1
    2
    3
    var_dump($bob->getName()); // Bob
    var_dump($adam->getName()); // Adam
    var_dump($billy->getName()); // child: Billy

    注意,我们每次都在执行Person::getName()实例方法。但我们正在使用parent::getName()在其中一个案例(儿童案例)中执行此操作。这就是这种方法的强大之处。好的。注意事项1

    注意,调用上下文决定是否使用实例。因此:好的。

    1
    2
    3
    4
    5
    class Foo {
        public function isFoo() {
            return $this instanceof Foo;
        }
    }

    并不总是正确的。好的。

    1
    2
    3
    4
    5
    6
    7
    class Bar {
        public function doSomething() {
            return Foo::isFoo();
        }
    }
    $b = new Bar;
    var_dump($b->doSomething()); // bool(false)

    现在这里真的很奇怪。我们调用的是另一个类,但是传递给Foo::isFoo()方法的$this$bar的实例。好的。

    这会导致各种各样的错误和概念性的错误。因此,我强烈建议避免::操作符在实例方法中使用除这三个虚拟"快捷"关键字(staticselfparent之外的任何方法。好的。注意事项2

    注意,静态方法和属性由每个人共享。这使得它们基本上是全局变量。所有的问题都是全球性的。因此,如果您不愿意将信息存储在真正的全局性中,那么我真的会犹豫是否将其存储在静态方法/属性中。好的。注意事项3

    一般来说,您需要使用static而不是self来使用所谓的后期静态绑定。但请注意,它们不是同一回事,所以说"总是使用static"而不是self)确实是短视的。相反,停止并考虑您想要进行的调用,如果您希望子类能够覆盖静态解析的调用,请进行思考。好的。TL/DR

    太糟糕了,回去读吧。可能太长了,但是太长了,因为这是一个复杂的主题好的。TL/DRα2

    好的,很好。简而言之,self用于引用类内的当前类名,其中,$this表示当前的对象实例。请注意,self是一个复制/粘贴快捷方式。你可以用你的类名安全地替换它,它会很好地工作。但是$this是一个动态变量,不能提前确定(甚至可能不是您的类)。好的。TL/DRα3

    如果使用了对象操作符(->),那么您总是知道您正在处理一个实例。如果使用范围解析操作符(::),则需要有关上下文的更多信息(我们已经在对象上下文中了吗?我们是在一个物体之外吗?等)。好的。好啊。


    不幸的是,自self美元)的类型,即是在靠近$this流实例的类。self是使用静态成员函数让你访问静态成员变量。$this是用在非静态成员函数和参考指南,是一个国家在其中的类成员函数被称为。

    因为this是一个对象,你使用它$this->member样:

    因为self是一个对象,它基本上是一个电流型自动指的是一流的,你使用它self::member样:


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

    1
    2
    Example:
    $derek = new Person();

    $derek现在是个人的一个具体实例。每个人都有名字和姓氏,但是$derek有一个特定的名字和姓氏(derek martin)。在$derek实例中,我们可以将其称为$this->first_name和$this->last_name。

    classname::用于引用该类型的类及其静态变量、静态方法。如果它有帮助,你可以用"共享"在精神上替换"静态"这个词。因为它们是共享的,所以它们不能引用$this,后者指的是特定的实例(不是共享的)。静态变量(即静态$db_连接)可以在对象类型的所有实例之间共享。例如,所有数据库对象共享一个连接(静态$connection)。

    静态变量示例:假设我们有一个包含单个成员变量的数据库类:静态$num_连接;现在,把它放到构造函数中:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    function __construct()
    {
        if(!isset $num_connections || $num_connections==null)
        {
            $num_connections=0;
        }
        else
        {
            $num_connections++;
        }
    }

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

    1
    2
    3
    4
    function __destruct()
    {
        $num_connections--;
    }

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

    1
    echo DB::num_connections;

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

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

    静态方法示例:

    1
    2
    3
    4
    5
    6
    public static function prettyName($first_name, $last_name)
    {
        echo ucfirst($first_name).' '.ucfirst($last_name);
    }

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

    如您所见,public静态函数prettyname对对象一无所知。它只是处理你传入的参数,就像一个普通函数,它不是对象的一部分。那么,如果我们不把它作为物体的一部分,为什么还要麻烦呢?

  • 首先,将函数附加到对象有助于保持事物的有序性,以便知道在哪里可以找到它们。
  • 第二,它防止命名冲突。在一个大型项目中,可能有两个开发人员创建getname()函数。如果一个创建了classname1::getname(),另一个创建了classname2::getname(),那么这完全没有问题。没有冲突。是静态方法!
  • 自我:如果要在具有要引用的静态方法的对象外部进行编码,则必须使用该对象的名称视图::格式"电话号码($phoneu number)"调用它;如果要在具有要引用的静态方法的对象内进行编码,则可以使用对象的名称视图::格式化电话号码($pn),也可以使用self::格式化电话号码($pn)快捷方式

    静态变量也是如此:示例:View::Templates_Path与Self::Templates_Path

    在db类中,如果我们引用其他对象的静态方法,我们将使用该对象的名称:示例:session::getUserSonline();

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

    希望这有助于解决问题。)


    从这篇博文:

    • self refers to the current class
    • self can be used to call static functions and reference static member variables
    • self can be used inside static functions
    • self can also turn off polymorphic behavior by bypassing the vtable
    • $this refers to the current object
    • $this can be used to call static functions
    • $this should not be used to call static member variables. Use self instead.
    • $this can not be used inside static functions

    在PHP中,使用self关键字访问静态属性和方法。

    问题是,您可以在任何地方用self::method()替换$this->method(),无论method()是否声明为静态。那么你应该用哪一个呢?

    考虑此代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    class ParentClass {
        function test() {
            self::who();    // will output 'parent'
            $this->who();   // will output 'child'
        }

        function who() {
            echo 'parent';
        }
    }

    class ChildClass extends ParentClass {
        function who() {
            echo 'child';
        }
    }

    $obj = new ChildClass();
    $obj->test();

    在本例中,self::who()将始终输出"parent",而$this->who()将取决于对象的类。

    现在我们可以看到self指的是它被调用的类,而$this指的是当前对象的类。

    因此,只有当$this不可用时,或者不想允许后代类覆盖当前方法时,才应该使用self。


    在类定义中,$this引用当前对象,self引用当前类。

    有必要使用self引用类元素,并使用$this引用对象元素。

    1
    2
    3
    self::STAT // refer to a constant value
    self::$stat // static variable
    $this->stat // refer to an object variable


    根据http://www.php.net /手动/恩/ language.oop5.static.php没有$self。在一个只读$this,指流的类的实例(对象),和自我,可以用来指一类静态成员。的差异之间的对象实例和一个类来这里玩。


    Here is an example of correct usage of $this and self for non-static
    and static member variables:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <?php
    class X {
        private $non_static_member = 1;
        private static $static_member = 2;

        function __construct() {
            echo $this->non_static_member . ' '
               . self::$static_member;
        }
    }

    new X();
    ?>

    self表示当前类(在其中称为当前类)。

    $this表示当前对象。你可以用静态而不是自我。参见示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
        class ParentClass {
                function test() {
                        self::which();  // output 'parent'
                        $this->which(); // output 'child'
                }

                function which() {
                        echo 'parent';
                }
        }

        class ChildClass extends ParentClass {
                function which() {
                        echo 'child';
                }
        }

        $obj = new ChildClass();
        $obj->test();

    输出:起源小孩


    因为这里没有人谈论性能,这里有一个小基准我做了(5.6):

    1
    2
    3
    4
    5
     Name     | Time    | Percent  
    ----------|---------|---------  
     $this->  | 0.99163 | 106.23%  
     self::   | 0.96912 | 103.82%  
     static:: | 0.93348 | 100%

    这些是2000 000次运行的结果,下面是我使用的代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    <?php

    require '../vendor/autoload.php';

    // My small class to do benchmarks
    // All it does is looping over every test x times and record the
    //   time it takes using `microtime(true)`
    // Then, the percentage is calculated, with 100% being the quickest
    // Times are being rouned for outputting only, not to calculate the percentages
    $b = new Tleb\Benchmark\Benchmark(2000000);

    class Foo
    {
        public function calling_this()
        {
            $this->called();
        }

        public function calling_self()
        {
            self::called();
        }

        public function calling_static()
        {
            static::called();
        }

        public static function called()
        {
        }
    }

    $b->add('$this->',  function () { $foo = new Foo; $foo->calling_this(); });
    $b->add('self::',   function () { $foo = new Foo; $foo->calling_self(); });
    $b->add('static::', function () { $foo = new Foo; $foo->calling_static(); });

    $b->run();


    我认为问题不在于是否可以通过调用ClassName::staticMember来调用类的静态成员。问题是使用self::classmember$this->classmember有什么区别。

    例如,无论您使用的是self::还是$this->,以下两个示例都没有任何错误。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    class Person{
        private $name;
        private $address;

        public function __construct($new_name,$new_address){
            $this->name = $new_name;
            $this->address = $new_address;
        }
    }

    class Person{
        private $name;
        private $address;
        public function __construct($new_name,$new_address){
            self::$name = $new_name;
            self::$address = $new_address;
        }
    }


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


    • 对象指针$this指向当前对象。
    • 类值"static"是指当前对象。
    • 类值"self"是指它在中定义的确切类。
    • 类值"parent"是指它在中定义的确切类的父级。

    请参见下面显示重载的示例。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    <?php

    class A {

        public static function newStaticClass()
        {
            return new static;
        }

        public static function newSelfClass()
        {
            return new self;
        }

        public function newThisClass()
        {
            return new $this;
        }
    }

    class B extends A
    {
        public function newParentClass()
        {
            return new parent;
        }
    }


    $b = new B;

    var_dump($b::newStaticClass()); // B
    var_dump($b::newSelfClass()); // A because self belongs to"A"
    var_dump($b->newThisClass()); // B
    var_dump($b->newParentClass()); // A


    class C extends B
    {
        public static function newSelfClass()
        {
            return new self;
        }
    }


    $c = new C;

    var_dump($c::newStaticClass()); // C
    var_dump($c::newSelfClass()); // C because self now points to"C" class
    var_dump($c->newThisClass()); // C
    var_dump($b->newParentClass()); // A because parent was defined *way back* in class"B"

    大多数时候,您希望引用当前类,这就是为什么使用static$this的原因。但是,有时您需要self,因为不管扩展什么,您都需要原始类。(非常,非常罕见)


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

    换句话说,使用self for staticthis for none-static members or methods

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


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

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

    http://ideone.com/7ethy

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    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;相反。


    我遇到了同样的问题,简单的答案是:

    • $这需要类的一个实例
    • 自我:不

    每当您使用静态方法或静态属性,并且希望在没有实例化类的对象的情况下调用它们时,您需要使用self::来调用它们,因为$这总是要求创建对象。


    如果您想调用一个类的方法而不创建该类的对象/实例,那么可以使用self,这样可以节省RAM(有时也可以使用self)。换句话说,它实际上是静态地调用一个方法。使用this进行对象透视。


    例1:使用self可用于类常量

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

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

    案例2:静态特性

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

    根据php.net,这里有三个特殊的关键字:selfparentstatic。它们用于从类定义内部访问属性或方法。

    另一方面,$this用于调用任何类的实例和方法,只要该类是可访问的。