核心要点
class_exists()
、get_class()
、get_parent_class()
和 is_subclass_of()
。这些函数提供有关类的基本信息,例如它们的名称、父类的名称等等。ReflectionClass
类是 API 的主要类,用于对类、接口和方法应用反射。PHP 内省机制是任何编程语言中的一种常见特性,它允许程序员操作对象类。当您在设计时不知道需要执行哪个类或方法时,您会发现内省特别有用。PHP 中的内省提供了检查类、接口、属性和方法的有用功能。PHP 提供大量可用于完成此任务的函数。为了帮助您理解内省,我将使用 PHP 中的示例简要概述一些 PHP 的类、方法和函数,以突出它们的使用方式。在本文中,您将看到一些关于如何使用一些最有用的 PHP 内省函数的示例,以及一个专门介绍提供类似于内省功能的 API(反射 API)的部分。
PHP 内省函数
在第一个示例中,我将演示一些 PHP 的内省函数。您可以使用这些函数来提取有关类的基本信息,例如它们的名称、父类的名称等等。
class_exists()
– 检查是否已定义类get_class()
– 返回对象的类名get_parent_class()
– 返回对象的父类的类名is_subclass_of()
– 检查对象是否具有给定的父类以下是包含 Introspection
和 Child
类定义的示例 PHP 代码,以及上面列出的函数提取的信息输出:
<code class="language-php"><?php class Introspection { public function description() { echo "I am a super class for the Child class.\n"; } } class Child extends Introspection { public function description() { echo "I'm " . get_class($this) , " class.\n"; echo "I'm " . get_parent_class($this) , "'s child.\n"; } } if (class_exists("Introspection")) { $introspection = new Introspection(); echo "The class name is: " . get_class($introspection) . "\n"; $introspection->description(); } if (class_exists("Child")) { $child = new Child(); $child->description(); if (is_subclass_of($child, "Introspection")) { echo "Yes, " . get_class($child) . " is a subclass of Introspection.\n"; } else { echo "No, " . get_class($child) . " is not a subclass of Introspection.\n"; } } ?></code>
上述代码的输出应如下所示:
<code class="language-php"><?php class Introspection { public function description() { echo "I am a super class for the Child class.\n"; } } class Child extends Introspection { public function description() { echo "I'm " . get_class($this) , " class.\n"; echo "I'm " . get_parent_class($this) , "'s child.\n"; } } if (class_exists("Introspection")) { $introspection = new Introspection(); echo "The class name is: " . get_class($introspection) . "\n"; $introspection->description(); } if (class_exists("Child")) { $child = new Child(); $child->description(); if (is_subclass_of($child, "Introspection")) { echo "Yes, " . get_class($child) . " is a subclass of Introspection.\n"; } else { echo "No, " . get_class($child) . " is not a subclass of Introspection.\n"; } } ?></code>
您可以使用 class_exists()
方法确定是否已定义给定的类,该方法采用表示要检查的所需类的名称的字符串参数,以及一个可选的布尔值,指示是否在过程中调用自动加载器。get_class()
和 get_parent_class()
方法分别返回对象的类名或其父类的类名。两者都将对象实例作为参数。is_subclass_of()
方法将对象实例作为其第一个参数,并将表示父类名的字符串作为第二个参数,并返回对象是否属于作为参数给出的类的子类。
以下是一个第二个示例,其中包含 ICurrencyConverter
接口和 GBPCurrencyConverter
类的定义,以及上面列出的函数提取的信息输出。与第一个示例一样,我将首先列出函数,然后向您展示一些代码。
get_declared_classes()
– 返回所有已声明类的列表get_class_methods()
– 返回类方法的名称get_class_vars()
– 返回类的默认属性interface_exists()
– 检查接口是否已定义method_exists()
– 检查对象是否定义了方法<code>The class name is: Introspection I am a super class for the Child class. I'm Child class. I'm Introspection's child. Yes, Child is a subclass of Introspection.</code>
上述代码的输出应如下所示:
<code class="language-php"><?php interface ICurrencyConverter { public function convert($currency, $amount); } class GBPCurrencyConverter implements ICurrencyConverter { public $name = "GBPCurrencyConverter"; public $rates = array("USD" => 0.622846, "AUD" => 0.643478); protected $var1; private $var2; function __construct() {} function convert($currency, $amount) { return $this->rates[$currency] * $amount; } } if (interface_exists("ICurrencyConverter")) { echo "ICurrencyConverter interface exists.\n"; } $classes = get_declared_classes(); echo "The following classes are available:\n"; print_r($classes); if (in_array("GBPCurrencyConverter", $classes)) { print "GBPCurrencyConverter is declared.\n"; $gbpConverter = new GBPCurrencyConverter(); $methods = get_class_methods($gbpConverter); echo "The following methods are available:\n"; print_r($methods); $vars = get_class_vars("GBPCurrencyConverter"); echo "The following properties are available:\n"; print_r($vars); echo "The method convert() exists for GBPCurrencyConverter: "; var_dump(method_exists($gbpConverter, "convert")); } ?></code>
正如您可能已经猜到的那样,interface_exists()
方法与第一个示例中讨论的 class_exists()
方法非常相似。它确定是否已定义给定的接口,并采用接口名称的字符串参数和可选的自动加载器布尔值。get_declared_classes()
方法返回一个包含所有已定义类的名称的数组,并且不带任何参数。根据您加载的库(编译到 PHP 中或使用 require
/include
加载),可能存在其他类。get_class_method()
将对象实例或表示所需类的字符串作为参数,并返回由类定义的方法名称数组。请注意,在 ICurrencyConverter
类中定义的所有属性以及 get_class_vars()
方法返回的所有属性中,只有 $name
和 $rates
出现在输出中。私有和受保护的属性被跳过了。
PHP 反射 API
PHP 通过其反射 API 支持反射。正如您从 PHP 手册中看到的那样,反射 API 比内省机制要慷慨得多,并提供了大量的类和方法,您可以使用它们来完成反射任务。ReflectionClass
类是 API 的主要类,用于对类、接口和方法应用反射,并提取有关所有类组件的信息。反射很容易在您的应用程序代码中实现,并且与内省一样,也非常直观。以下是一个使用 ICurrencyConverter
接口和 Child
和 GBPCurrencyConverter
类相同定义来说明反射的示例:
<code class="language-php"><?php class Introspection { public function description() { echo "I am a super class for the Child class.\n"; } } class Child extends Introspection { public function description() { echo "I'm " . get_class($this) , " class.\n"; echo "I'm " . get_parent_class($this) , "'s child.\n"; } } if (class_exists("Introspection")) { $introspection = new Introspection(); echo "The class name is: " . get_class($introspection) . "\n"; $introspection->description(); } if (class_exists("Child")) { $child = new Child(); $child->description(); if (is_subclass_of($child, "Introspection")) { echo "Yes, " . get_class($child) . " is a subclass of Introspection.\n"; } else { echo "No, " . get_class($child) . " is not a subclass of Introspection.\n"; } } ?></code>
上述代码的输出应如下所示:
<code>The class name is: Introspection I am a super class for the Child class. I'm Child class. I'm Introspection's child. Yes, Child is a subclass of Introspection.</code>
getInterfaceNames()
方法返回一个包含类实现的接口名称的数组。getParentClass()
方法可以返回父类的 ReflectionClass
对象表示,如果不存在父类则返回 false。要列出 ReflectionClass
对象的名称,您可以使用 getName()
方法,如上面的代码所示。getMethods()
方法检索方法数组,并且可以将 ReflectionMethod::IS_STATIC
、IS_PUBLIC
、IS_PROTECTED
、IS_PRIVATE
、IS_ABSTRACT
和 IS_FINAL
的位掩码组合作为可选参数,以根据可见性过滤列表。反射 API 提供了反射的良好实现,使您可以创建更复杂的应用程序,例如 ApiGen,但进一步讨论超出了本文的目标。
总结
在本文中,您已经了解了如何使用 PHP 的内省函数和反射 API 来获取有关类、接口、属性和方法的信息。提取此信息的目的在于在运行时更好地了解您的代码并创建复杂的应用程序。
(图片来自 Fotolia)
(关于 PHP 中内省和反射的常见问题 (FAQ)) 此处省略了FAQ部分,因为篇幅过长,且与伪原创目标不符。 如有需要,可以单独提出FAQ问题。
以上是PHP的内省和反射的详细内容。更多信息请关注PHP中文网其他相关文章!