静态差异::类 vs get_called_class() 和 __CLASS__ vs get_class() vs self::类

2022-08-30 21:14:25

我见过几个线程,人们问如何在PHP中获取类或对象的名称。但是,我在任何地方都看不到所解释的各种可能性之间的区别。我希望这里的有人能帮助我。

因此,为了获得被调用类的类名,我知道两种可能性:

  1. get_called_class()

  2. static::class

(get_class($this)对于非静态类)

为了获取放置代码的类的类名,我知道以下三种可能性:

  1. get_class()

  2. __CLASS__

  3. self::class

我现在有什么可以忽略的差异吗?一种方式相对于另一种方式的潜在冒险和劣势是什么?


答案 1

差异

get_class()

返回对象类的名称

当您将对象实例指针作为第一个也是唯一一个参数传递时,它将返回一个类名,包括当前类(不带参数)或任何指定对象实例的限定命名空间。

__CLASS__

一个魔术常量,它返回限定的命名空间和当前类名。在这里,您无法测试其他对象的类名。根据 PHP 5.4,它适用于特征。也就是说,当在类中使用该特征时,它将返回该类的命名空间和名称。

::class

仅从 PHP 5.5 开始可用。它使用类名和命名空间解析来获取信息,因此它不需要事先实例化类。另请注意:

使用 ::class 的类名解析是编译时转换。这意味着在创建类名字符串时,尚未发生自动加载。因此,即使类不存在,类名也会扩展。在这种情况下,不会发出任何错误。

测试

<?php
namespace nTest;
trait tTest {
  function __toString() {return get_class();}
  function className() {return __CLASS__;}  // per PHP 5.4
  function traitName() {return __TRAIT__;}
}
class cTest {
  use tTest;
  function usedTraitName() {return __TRAIT__;}
}
class cClassWithoutObject {}
$oTest = new cTest;

header('Content-type: text/plain');
print                                  // Output:
    $oTest . PHP_EOL                   // 'nTest::cTest'
  . get_class($oTest) . PHP_EOL        // 'nTest::cTest'
  . $oTest->className() . PHP_EOL      // 'nTest::cTest'
  . $oTest->traitName() . PHP_EOL      // 'nTest::tTest' (trait!)
  . $oTest->usedTraitName() . PHP_EOL  // '' (no trait!)
  . cTest::class . PHP_EOL             // 'nTest::cTest'
  . cClassWithoutObject::class;        // 'nTest::cTestNotInstantiated'

答案 2

如果您使用继承,那么这一点之间的一个重要区别是,它将为您提供包含该代码的类的名称(可以是父类),而将为您提供运行时的具体类的名称。__CLASS__get_class($this)__CLASS__get_class($this)$this

例:

class Animal {

    function printCompileTimeType() {

        echo __CLASS__;
    }

    function printOverridableCompileTimeType() {

        echo __CLASS__;
    }

    function printType() {

        echo get_class($this);
    }
}

class Dog extends Animal {

    function printOverridableCompileTimeType() {

        echo __CLASS__;
    }
}

$animal = new Animal();
$dog = new Dog();

$animal->printCompileTimeType(); // Prints 'Animal'.
$animal->printOverridableCompileTimeType(); // Prints 'Animal'.
$animal->printType(); // Prints 'Animal'.

$dog->printCompileTimeType(); // Prints 'Animal'.
$dog->printOverridableCompileTimeType(); // Prints 'Dog'.
$dog->printType(); // Prints 'Dog'.

我会说它通常更有用,因为无论您从哪里使用它,它都可以预测地工作,而无需编写重复的覆盖代码,例如.get_class($this)printOverridableCompileTimeType


推荐