PHP面向物件深入理解之五(內省函式與反射類)
1. 內省(Introspection)函式
Introspection(內省)程式在執行時檢查物件的型別或屬性的能力,他允許物件類由程式設計師操縱。
你將會發現introspection 相當有用當你不知道哪一個類後或者方法在設計時需要被執行.
Introspection 在 PHP 提供非常有用的能力去檢查類(classes), 介面(interfaces), 屬性(properties),
和方法(methods). PHP 提供了大量的函式你能用他來完成這些檢查任務.
為了幫助你理解introspection, 我將簡要概述一些 PHP的 類(classes),方法(methods
他們被使用的時候,程式碼會高亮顯示.
通過這篇文章, 你將會看到一組例子如何去使用一些非常有用的 PHP的 introspection 函式
以及專門針對API提供類似於introspection功能的部分, 反射(Reflection) API.
第一個例子, 我會展示一些 PHP的 introspection
functions. 你能使用這些功能functions
去檢查基礎的資訊包括關於類(classes)像他們的名字(name), 父類的名字等等.
<?php class_exists() # 檢查一個類是否被定義 get_class() # 返回物件的類名 get_parent_class() # 返回物件的類的父類名 is_subclass_of() # 檢查一個物件是否是給定父類的 子類 ?>
下面是一個例子 PHP 包含定義Introspection 和子類以及輸出輸出通過上述功能提取的資訊:
<?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"; } } ?>
輸出如下:
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.
這是第二個例子,其中包含ICurrencyConverter介面和GBPCurrencyConverter類的定義,
並輸出上面列出的函式提取的資訊。 與第一個例子一樣,我將首先列出這些函式,然後顯示一些程式碼。
<?php
get_declared_classes() # 返回一系列已經定義的類
get_class_methods() # 返回給定【類|物件】的所有方法 private 和 protected 方法會被跳過
get_class_vars() # 返回當前【類名】的預設屬性 private 和 protected 屬性會被跳過
interface_exists() # 檢查某個【介面名】是否 被定義
method_exists() # 檢查一個類/物件是否定義某個方法
?>
我們看個栗子:
<?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 $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"));
}
輸出如下:
ICurrencyConverter interface exists.
The following classes are available:
Array
(
[0] => stdClass
[1] => Exception
[2] => ErrorException
[3] => Closure
[4] => DateTime
[5] => DateTimeZone
[6] => DateInterval
[7] => DatePeriod
...
[154] => GBPCurrencyConverter
)
GBPCurrencyConverter is declared.
The following methods are available:
Array
(
[0] => __construct
[1] => convert
)
The following properties are available:
Array
(
[name] => GBPCurrencyConverter
[rates] => Array
(
[USD] => 0.622846
[AUD] => 0.643478
)
)
2. 反射(Reflection)API
PHP通過他的Reflection類 API支援反射. 就像你在php官方手冊中看到的,
Reflection類API比 introspection 方法更慷慨,提供了大量的類(classes)和(methods)
可以用來完成反射任務. ReflectionClass 是 API的主類 並用於對類,介面和方法應用反射,
並提取有關所有類元件的資訊。Reflection在應用程式程式碼中很容易實現,像內省一樣也很直觀。
下面有個例子來解釋 reflection使用相同的定義 ICurrencyConverter 介面
以及子類 GBPCurrencyConverter:
<?php
$child = new ReflectionClass("Child");
$parent = $child->getParentClass();
echo $child->getName() . " is a subclass of " . $parent->getName() . ".n";
$reflection = new ReflectionClass("GBPCurrencyConverter");
$interfaceNames = $reflection->getInterfaceNames();
if (in_array("ICurrencyConverter", $interfaceNames)) {
echo "GBPCurrencyConverter implements ICurrencyConverter.n";
}
$methods = $reflection->getMethods();
echo "The following methods are available:n";
print_r($methods);
if ($reflection->hasMethod("convert")) {
echo "The method convert() exists for GBPCurrencyConverter.n";
}
?>
下面是輸出:
Child is a subclass of Introspection.
GBPCurrencyConverter implements ICurrencyConverter.
The following methods are available:
Array
(
[0] => ReflectionMethod Object
(
[name] => __construct
[class] => GBPCurrencyConverter
)
[1] => ReflectionMethod Object
(
[name] => convert
[class] => GBPCurrencyConverter
)
)
getInterfaceNames() 返回當前類例項化的介面的名字.
getParentClass() 返回一個
ReflectionClass 物件 表示這個父類或者 false(如果沒有父類的話).
為了列舉出 ReflectionClass 物件的名字, 你可以使用
getName() 方法, 就像你在上面的方法中看到的.
getMethods() 方法返回了一個數組的方法 還可以加一個可選引數
ReflectionMethod::IS_STATIC,IS_PUBLIC,
IS_PROTECTED,IS_PRIVATE, IS_ABSTRACT, 和IS_FINAL 過率掉基於可見的方法
Reflection API 提供了一個好的實現給你反射的能力去建立更好的應用, 像 ApiGen, 雖然進一步的討論超出了本文的目標.
總結
這篇文章裡你已經看到了如何去使用 PHP的 內省函式 和 反射 API 來獲取得到資訊關於類, 介面, 屬性, 和 方法. 獲取這些資訊的目的是在執行時更好地瞭解您的程式碼,並建立複雜的應用程式。
相關推薦
PHP面向物件深入理解之五(內省函式與反射類)
1. 內省(Introspection)函式 Introspection(內省)程式在執行時檢查物件的型別或屬性的能力,他允許物件類由程式設計師操縱。 你將會發現introspection 相當有用當你不知道哪一個類後或者方法在設計時需要被執行. Introspectio
PHP面向物件深入理解之二(封裝、繼承、多型、克隆)
1.封裝 所謂封裝就是隱藏內部實現細節,提供外部訪問方式 將一系列私有的特徵儲存起來 class Person { private $ID; public function setID($id) { $this
PHP面向物件的理解(1)
PHP中虛擬函式的理解: 相比其他語言,如C++,PHP語言有很多不同之處。 看個例子: <?php // 定義父類 class P { public function name(){ echo "P::name() is called.
CSS深入理解之overflow(HTML/CSS)
clas alt span doc 邊距 蘊含 top overflow 會同 簡介 overflow看上去其貌不揚,其中蘊含的知識點還是很多的,有很多鮮為人知的特性表現。 overflow基本屬性值 1、visible(默認) 2、hidden 3、scroll 4、
《深入理解計算機系統(原書第三版)》pdf附網盤下載連結+(附一個菜鳥的java學習之路)
技術書閱讀方法論 一.速讀一遍(最好在1~2天內完成) 人的大腦記憶力有限,在一天內快速看完一本書會在大腦裡留下深刻印象,對於之後複習以及總結都會有特別好的作用。 對於每一章的知識,先閱讀標題,弄懂大概講的是什麼主題,再去快速看一遍,不懂也沒有關係,但是一定要在不懂的
JAVA面向物件高階特性之繼承(1)常見問題解答
1、什麼是繼承? 答:如果說A是一個B,則我們說A繼承自B。通過繼承來實現程式碼的複用。 2、Java中如何實現繼承? 答:Java類通過extends關鍵字實現繼承,所有的類都間接或者直接繼承自Object類。 3、Java中,有繼承關係時,變數隱藏的原則? 答:子類
Mininet(輕量級軟件定義網絡和測試平臺) 之五(ARP攻擊與防範)
mininet ARP ettercap Mininet-5 延續上一個實驗(mininet-4),本次實驗要模擬arp 攻擊 以及 如何防治arp攻擊 角色 h1 為使用者,不停的去跟h2溝通 h4 為攻擊者,企圖去竊聽h1與h2溝通的資訊 所需安裝套件 sudo
javascript面向物件程式設計--惰性例項化(實現按需例項化)
javascript是以物件為基礎,以函式為模型,以原型為繼承機制的開發模式 惰性例項化:避免在頁面中使用javascript初始化執行時就例項化類,而是將一些類的例項化推遲到需要時候才去例項化,避免資源過早的消耗 var myNamespace=function(){ &
Spark-MLlib的快速使用之五(梯度提升樹GBT 迴歸)
(1)描述 梯度提升樹(GBT)是決策樹的集合。 GBT迭代地訓練決策樹以便使損失函式最小化。 spark.ml實現支援GBT用於二進位制分類和迴歸,可以使用連續和分類特徵。 (2)測試資料 1 153:5 154:63 155:197 181:20 182:254 183:230 1
《深入理解計算機系統(原書第三版)》pdf
目錄 · · · · · · 出版者的話 中文版序一 中文版序二 譯者序 前言 關於作者 第1章 計算機系統漫遊1 1.1 資訊就是位+上下文1 1.2 程式被其他程式翻譯成不同的格式3 1.3 瞭解編譯系統如何工作是大有益處的4 1.4 處理器讀並解釋儲存
深入理解計算機系統(原書第三版)練習題2.6 感性認識整型和浮點型別(同一個數)在機器中表示
/** * 練習題2.6 感性認識整型和浮點型別(同一個數)在機器中表示 * 由於我的機器是小端表示,將列印結果還原真實數並用二進位制表示 * 41913500 -->(還原) 0x00359141 -->(二進位制) 0000 0000 0011 0101
Python之NumPy(axis=0 與axis=1)區分
tail ner def ros som 分享 然而 article 本質 轉自:http://blog.csdn.net/wangying19911991/article/details/73928172 https://www.zhihu.com/
Hive之DML(資料匯入與資料匯出)操作
總結: 資料的匯入 1)hdfs或者本地檔案匯入使用 load 或者 建立資料庫的同時指定檔案位置 location 2)從已有hive資料庫中表匯入相應的資料 使用 as
MFC中關於檔案的讀取和儲存(使用CFile與CFileDialog類)
CFile::modeCreate 構造新檔案,如果檔案存在,則長度變為0 CFile::modeNoTruncate 該屬性和modeCreate聯合使用,可以達到如下效果:如果檔案存在,則不會將檔案的長度置為0,如果不存在,則會由modeCreate屬性來建立一個新檔案。
淺談PHP面向物件程式設計(五)
5.0 繼承 5.1 繼承的概念 在現實生活中,繼承一般指的是子女繼承父輩的財產。在程式中,繼承描述的是事物之間的所屬關係,通過繼承可以使許多事物之間形成一種關係體系 。 例如貓和狗都屬於動物,程式中便可以描述為貓和
深入PHP面向物件、模式與實踐——模式原則(1)
組合 模式的啟示 通過以靈活的方式來組合物件,元件能在執行時被定義。《設計模式》將此提煉出一個原則:組合優於繼承。 組合與繼承 繼承是應對變化的環境及上下文設計的有效方式,然而它會限制靈活性,尤其是當類承擔了過多的責任的時候。 問題 以下圖
php面向物件之多型(1)
利用java來引入多型 買一個手電筒(說明書上寫的手電筒只能裝紅玻璃),和幾個不同顏色的玻璃片,目的是裝上不同的玻璃片,顯示不同的顏色 public class PolyTest { public static void main(String[
PHP面向物件之介面
PHP與大多數面向物件程式語言一樣,不支援多重繼承。也就是說每個類 只能繼承一個父類。 為了解決此問題,PHP引入了介面。 介面的思想是指定了一個實現該介面的類必須實現的一系列方法。 介面是一種特殊的抽象類,抽象類是一種特殊的類,所以介面也是一種特殊的類。 為什
淺談PHP面向物件程式設計(九)
9.0 設計模式 在編寫程式時經常會遇到一此典型的問題或需要完成某種特定需求,設計模式就是針對這些問題和需求,在大量的實踐中總結和理論化之後優選的程式碼結構程式設計風格,以及解決問題的思考方式。 設計模式就像是經典的棋譜。不同的棋局,使用不同的棋諧,免得自己再去思考和模索。本節將針對PHP應用程式
php面向物件(目錄操作)
目錄操作 建立目錄 Mkdir(目錄地址,許可權,是否遞迴建立=false); Rmdir(目錄地址) 刪除目錄 僅僅可以刪除空目錄。(不支援遞迴刪除) 移動(改名) Rename(舊地址,新地址) 該函式也支援操作檔案。 獲取目錄內容(檔案) 開啟目錄 目錄控制代碼