什么时候使用自我超过$?

Casey Watson 1854 php scope class

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

什么时候适合?

John Milliki.. 1587

简答

使用$this来指代当前对象.用self指当前类.换句话说, $this->member用于非静态成员,self::$member用于静态成员.

完整答案

以下是正确使用$thisself非静态和静态成员变量的示例:

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

这里是一个例子不正确的使用$thisself用于非静态和静态成员变量:

<?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对成员函数:

<?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:

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

这个想法是$this->foo()调用foo()当前对象的确切类型的成员函数.如果对象是type X,它就这样调用X::foo().如果对象是type Y,则调用Y::foo().但是对于self :: foo(),X::foo()总是被调用.

来自http://www.phpbuilder.com/board/showthread.php?t=10354489:

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

  • 这个答案过于简单化了.正如其他答案所指出的那样,`self`与范围解析运算符`::`一起使用来引用当前类; 这可以在静态和非静态上下文中完成.另外,使用`$ this`来调用静态方法(但不能引用字段)是完全合法的. (313认同)
  • 如果您使用的是5.3+,还可以考虑使用static ::而不是:: self.这可能会让你头疼不已,请参阅下面的答案,了解原因. (47认同)
  • -1.这个答案有误导性,请阅读其他答案以获取更多信息. (25认同)
  • 它可能过于简化,但它解决了我的基本问题而没有让我的头爆炸.我确实得到了一些我发现有用的更多信息,但是现在我只想弄清楚为什么我用$ this-> attrib命中我的类属性,用self :: constant命中类常量.这有助于我更好地理解 (3认同)

用户甲.. 720

关键字自不只是指"当前类的,至少不会在限制你的静态成员的一种方式.在非静态成员的上下文中,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->之间差异的最好例子,但是通过首先反驳一个概念来隐藏它是一种耻辱. (3认同)
  • @adjwilli:为什么那种糟糕的风格?如果OP的期望(论点)首先被反对(对立)然后解释作为综合给出,它是否会提高意识? (3认同)

Sqoo.. 436

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

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

class Person
{

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

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

}

如果我们打电话,Person::status()我们会看到"人还活着".现在考虑当我们创建一个继承自this的类时会发生什么:

class Deceased extends Person
{

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

}

调用Deceased::status()我们希望看到"Person is deceased"但是我们看到的是"Person is alive",因为范围包含定义调用时的原始方法定义self::getStatus().

PHP 5.3有一个解决方案.在static::分辨率操作实现"晚静态绑定",这是说,它必然要调用的类范围的一个奇特的方式.将行更改status()static::getStatus(),结果是您所期望的.在旧版本的PHP中,你必须找到一个kludge来做到这一点.

请参阅PHP文档

所以回答问题不是问...

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

  • "呼唤已故:: status()我们希望看到"人死了"".不.这是一个静态函数调用,因此不涉及多态. (45认同)
  • 类常量怎么样? (5认同)
  • 这个例子让我感到困惑:我认为`getStatus`方法是我要调用的一个类实例,而不是类. (2认同)

ircmaxell.. 234

为了真正理解我们在谈论self对比时所谈论的内容$this,我们需要真正深入研究在概念和实践层面上发生的事情.我真的觉得没有任何答案能够做到这一点,所以这是我的尝试.

让我们先谈谈一个和一个对象是什么.

从概念上讲,类和对象

那么,什么?很多人将它定义为对象的蓝图模板.实际上,您可以在此处阅读有关PHP中的类的更多信息.在某种程度上,这就是它的真实含义.我们来看一堂课:

class Person {
    public $name = 'my name';
    public function sayHello() {
        echo "Hello";
    }
}

正如您所知,该类上有一个属性,并且调用$name了一个方法(函数)sayHello().

这是非常值得注意的是,重要的是静态结构.这意味着Person,一旦定义,该类在您看到的任何地方始终都是相同的.

另一方面,对象是所谓的类的实例.这意味着我们采用类的"蓝图",并使用它来制作动态副本.此副本现在专门与其存储的变量相关联.因此,对实例的任何更改都是该实例的本地更改.

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

我们使用运算符创建类的新实例new.

因此,我们说Class是一个全局结构,Object是一个本地结构.不要担心这个有趣的->语法,我们将稍微介绍一下.

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

定义国家

那么让我们深入了解一个类实际包含的内容.一个类包含5种类型的"东西":

  1. 属性 - 将这些视为每个实例将包含的变量.

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

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

    class Foo {
        public function bar() {}
    }
    
  4. 静态方法 - 这些是在整个类中共享的函数.它们不在实例上运行,而是仅在静态属性上运行.

    class Foo {
        public static function bar() {}
    }
    
  5. 常量 - 类解析常量.这里没有更深入,但添加完整性:

    class Foo {
        const BAR = 1;
    }
    

所以基本上,我们使用关于静态的 "提示"在类和对象容器上存储信息,这些信息标识信息是否是共享的(因而是静态的)(因此是动态的).

状态和方法

在方法内部,对象的实例由$this变量表示.该对象的当前状态就在那里,并且改变(改变)任何属性将导致对该实例的改变(但不改变其他属性).

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

这里有趣的是如何进行静态调用.那么让我们谈谈我们如何访问状态:

进入国家

所以现在我们已经存储了那个状态,我们需要访问它.这能有点棘手(或方式比多一点),所以让我们这个分成两种观点:从一个实例/类外(从普通的函数调用说,还是从全球范围),以及一个实例内部/ class(来自对象上的方法).

来自实例/类的外部

从实例/类的外部,我们的规则非常简单且可预测.我们有两个运算符,每个运算符都会立即告诉我们是否正在处理实例或静态类:

  • ->- object-operator - 当我们访问实例时总是使用它.

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

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

  • ::- scope-resolution-operator - 始终用于访问Class静态属性或方法.

    echo Foo::bar()
    

    另外,我们可以用相同的方式在对象上调用静态方法:

    echo $foo::bar()
    

    这是非常需要注意的是,我们这样做时,重要的来自外部的对象的实例从隐藏的bar()方法.这意味着它与运行完全相同:

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

因此,$this静态调用中未定义.

从实例/类的内部

事情在这里有所改变.使用相同的运算符,但它们的含义变得非常模糊.

对象的操作 ->仍然是用来对对象的实例状态的呼叫.

class Foo {
    public $a = 1;
    public function bar() {
        return $this->a;
    }
}

使用object-operator:bar()$foo(一个实例Foo)上调用方法$foo->bar()将导致实例的版本为$a.

这就是我们的期望.

::运营商的意义虽然有所改变.它取决于对当前函数的调用的上下文:

  • 在静态上下文中

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

    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::baz()的内Foo类(它的任何方法).

  • parent - 这是指当前类的父级.

  • static - 这指的是被叫类.由于继承,子类可以覆盖方法和静态属性.因此,使用static而不是类名称来调用它们可以让我们解决调用的来源,而不是当前级别.

例子

理解这一点的最简单方法是开始查看一些示例.我们选一节课:

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

现在,我们也在看这里的继承.暂时忽略这是一个糟糕的对象模型,但让我们来看看当我们玩这个时会发生什么:

$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,我们可以在子类中覆盖它).

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

请注意,我们每次都在执行Person::getName() 实例方法.但我们正在使用parent::getName()其中一个案例(子案例).这就是使这种方法变得强大的原因.

谨慎的话#1

请注意,调用上下文决定了是否使用了实例.因此:

class Foo {
    public function isFoo() {
        return $this instanceof Foo;
    }
}

并非总是如此.

class Bar {
    public function doSomething() {
        return Foo::isFoo();
    }
}
$b = new Bar;
var_dump($b->doSomething()); // bool(false)

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

这可能会导致各种错误和概念性的WTF-ery.所以我强烈建议避免了::运营商从实例方法中的任何东西,除了这三个虚拟的"捷径"关键字(static,self,和parent).

谨慎的话#2

请注意,每个人都共享静态方法和属性.这使它们基本上成为全局变量.与全局变量相同的问题.所以我真的会犹豫是否要将信息存储在静态方法/属性中,除非你对它真正的全局性感到满意.

谨慎的话#3

一般来说,你会想要使用所谓的Late-Static-Binding来static代替self.但要注意它们不是同一个东西,所以说"总是使用static而不是self真正的短视.相反,停下来思考你想做的调用,并思考你是否希望子类能够覆盖那个静态解析呼叫.

TL/DR

太糟糕了,回去看看吧.它可能太长了,但它很长,因为这是一个复杂的话题

TL/DR#2

好的.简而言之,self用于引用类中的当前类名,其中as $this引用当前对象实例.请注意,这self是一个复制/粘贴快捷方式.您可以安全地用您的班级名称替换它,它会正常工作.但这$this是一个动态变量,无法提前确定(甚至可能不是你的班级).

TL/DR#3

如果使用了对象操作符(->),那么你总是知道你正在处理一个实例.如果使用scope-resolution-operator(::),您需要有关上下文的更多信息(我们是否已经在对象上下文中?我们是否在对象之外?等等).

  • 很高兴为self :: $ property和self :: property之间的区别添加一个清晰的解释; 我觉得那也很混乱 (3认同)
  • 在完整地阅读了长篇描述之后,我觉得懒得再次向上滚动以提升它.只是开玩笑,我做了upvote它:D.谢谢这非常有用. (2认同)

MrZebra.. 113

self(不是$ self)指的是类的类型,其中as $this指的是类的当前实例. self用于静态成员函数,以允许您访问静态成员变量.$this用于非静态成员函数,并且是对调用成员函数的类的实例的引用.

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

因为self它不是一个对象,它基本上是一个自动引用当前类的类型,你使用它:self::member


lo_fye.. 94

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

Example: 
$derek = new Person();

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

ClassName ::用于引用该类型的类及其静态变量,静态方法.如果有帮助,您可以在心理上将"静态"替换为"共享".因为它们是共享的,所以它们不能引用$ this,它引用特定的实例(不共享).静态变量(即静态$ db_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模式).

静态方法(即公共静态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);

如您所见,public static function prettyName对该对象一无所知.它只是处理你传入的参数,就像一个不属于对象的普通函数.那么,为什么我们可以把它作为对象的一部分呢?

  1. 首先,将函数附加到对象可以帮助您保持组织有序,因此您知道在哪里可以找到它们.
  2. 其次,它可以防止命名冲突.在一个大项目中,您可能有两个开发人员创建getName()函数.如果一个创建一个ClassName1 :: getName(),另一个创建ClassName2 :: getName(),那就没问题了.没有冲突.耶的静态方法!

SELF :: 如果您在具有要引用的静态方法的对象之外进行编码,则必须使用对象的名称View :: format_phone_number($ phone_number)调用它; 如果您在编码里面有你要引用静态方法的对象,就可以任意使用对象的名称查看:: format_phone_number($ PN),或者你可以使用自助:: format_phone_number($ PN)的快捷方式

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

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

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

希望有助于清理事情:)

  • 你的第二段文字中有$ ronny,但除非我错了,应该是$ derek. (2认同)

okconfused.. 27

来自这篇博文:

  • self 是指当前的类
  • self 可用于调用静态函数和引用静态成员变量
  • self 可以在静态函数中使用
  • self 也可以通过绕过vtable来关闭多态行为
  • $this 指当前的对象
  • $this 可用于调用静态函数
  • $this不应该用来调用静态成员变量.请self改用.
  • $this 不能在静态函数内部使用


用户甲.. 23

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

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

考虑以下代码:

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 .


Tarun Singha.. 19

在类定义中,$ this指的是当前对象,而self指的是当前类.

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

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


Mohit Bumb.. 18

以下是对非静态和静态成员变量正确使用$ this和self的示例:

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


cruizer.. 17

根据http://www.php.net/manual/en/language.oop5.static.php没有$self.仅$this用于引用类(对象)的当前实例和self,它可用于引用类的静态成员.对象实例和类之间的区别在这里发挥作用.

  • 建议:绊倒酸时,请阅读此答案. (6认同)

用户甲.. 12

我相信问题不在于您是否可以通过调用来调用类的静态成员ClassName::staticMember.问题是使用self::classmember和之间有什么区别$this->classmember.

例如,以下两个示例都可以正常运行,无论您使用的是self::还是$this->

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;
    }
}

  • `致命错误:访问未声明的静态属性:第16行的D:\ LAMP\www\test.php中的Person :: $ name (2认同)

tleb.. 12

由于这里没有人谈到表演,这里有一个小基准(5.6):

 Name     | Time    | Percent  
----------|---------|---------  
 $this->  | 0.99163 | 106.23%  
 self::   | 0.96912 | 103.82%  
 static:: | 0.93348 | 100%

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

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

  • 理论上它应该需要1个处理器时钟周期,这使得这些天大约为"1/2e9 s = 0.5 ns" (2认同)

Kabir Hossai.. 12

self 引用当前类(在其中调用它),

$this指当前对象.你可以使用static而不是self.看例子:

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

输出:父子


用户甲.. 11

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


Xeoncross.. 11

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

请参阅以下显示重载的示例.

<?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"

大多数时候你想引用当前的类,这就是你使用staticor的原因$this.但是,有时您需要 self因为您想要原始类而不管扩展它的内容.(很少,很少)


用户甲.. 5

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

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

在子/父场景中self / parent也主要用于识别子类和父类成员和方法.


fyrye.. 5

此外,$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;