1. 程式人生 > >PHP面向物件深入理解之五(內省函式與反射類)

PHP面向物件深入理解之五(內省函式與反射類)

1. 內省(Introspection)函式

Introspection(內省)程式在執行時檢查物件的型別或屬性的能力,他允許物件類由程式設計師操縱。
你將會發現introspection 相當有用當你不知道哪一個類後或者方法在設計時需要被執行.

Introspection 在 PHP 提供非常有用的能力去檢查類(classes), 介面(interfaces), 屬性(properties), 
和方法(methods). PHP 提供了大量的函式你能用他來完成這些檢查任務. 
為了幫助你理解introspection, 我將簡要概述一些 PHP的 類(classes),方法(methods

), 和函式(functions)
他們被使用的時候,程式碼會高亮顯示.

通過這篇文章, 你將會看到一組例子如何去使用一些非常有用的 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_PRIVATEIS_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深入理解overflowHTML/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

PythonNumPyaxis=0 axis=1區分

tail ner def ros som 分享 然而 article 本質 轉自:http://blog.csdn.net/wangying19911991/article/details/73928172 https://www.zhihu.com/

HiveDML資料匯入資料匯出操作

總結: 資料的匯入 1)hdfs或者本地檔案匯入使用  load 或者 建立資料庫的同時指定檔案位置 location 2)從已有hive資料庫中表匯入相應的資料    使用       as   

MFC中關於檔案的讀取和儲存使用CFileCFileDialog

       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(舊地址,新地址) 該函式也支援操作檔案。 獲取目錄內容(檔案) 開啟目錄 目錄控制代碼