PHP面向对象程序设计之类与反射API详解


Posted in PHP onDecember 02, 2016

本文实例讲述了PHP面向对象程序设计之类与反射API。分享给大家供大家参考,具体如下:

了解类

class_exists验证类是否存在

<?php
// TaskRunner.php
$classname = "Task";
$path = "tasks/{$classname}.php";
if ( ! file_exists( $path ) ) {
  throw new Exception( "No such file as {$path}" ); //抛出异常,类文件不存在
}
require_once( $path );
$qclassname = "tasks\\$classname";
if ( ! class_exists( $qclassname ) ) {
  throw new Exception( "No such class as $qclassname" ); //抛出异常,类不存在Fatal error: Uncaught exception 'Exception' with message 'No such class as tasks\Task'
Stack trace:
#0 {main}
}
$myObj = new $qclassname();
$myObj->doSpeak();
?>

get_class 检查对象的类 instanceof 验证对象是否属于某个类

<?php
class CdProduct {}
function getProduct() {
  return new CdProduct(  "Exile on Coldharbour Lane",
                "The", "Alabama 3", 10.99, 60.33 ); // 返回一个类对象
}
$product = getProduct();
if ( get_class( $product ) == 'CdProduct' ) {
  print "\$product is a CdProduct object\n";
}
?>
<?php
class CdProduct {}
function getProduct() {
  return new CdProduct(  "Exile on Coldharbour Lane",
                "The", "Alabama 3", 10.99, 60.33 );
}
$product = getProduct();
if ( $product instanceof CdProduct ) {
  print "\$product is a CdProduct object\n";
}
?>

get_class_methods 得到类中所有的方法列表,只获取public的方法,protected,private的方法获取不到。默认的就是public。

<?php
class CdProduct {
  function __construct() { }
  function getPlayLength() { }
  function getSummaryLine() { }
  function getProducerFirstName() { }
  function getProducerMainName() { }
  function setDiscount() { }
  function getDiscount() { }
  function getTitle() { }
  function getPrice() { }
  function getProducer() { }
}
print_r( get_class_methods( 'CdProduct' ) );
?>

output:

Array
(
  [0] => __construct
  [1] => getPlayLength
  [2] => getSummaryLine
  [3] => getProducerFirstName
  [4] => getProducerMainName
  [5] => setDiscount
  [6] => getDiscount
  [7] => getTitle
  [8] => getPrice
  [9] => getProducer
)

更多验证

<?php
class ShopProduct {}
interface incidental {};
class CdProduct extends ShopProduct implements incidental {
  public $coverUrl;
  function __construct() { }
  function getPlayLength() { }
  function getSummaryLine() { }
  function getProducerFirstName() { }
  function getProducerMainName() { }
  function setDiscount() { }
  function getDiscount() { }
  function getTitle() { return "title\n"; }
  function getPrice() { }
  function getProducer() { }
}
function getProduct() {
  return new CdProduct();
}
$product = getProduct(); // acquire an object
$method = "getTitle";   // define a method name
print $product->$method(); // invoke the method
if ( in_array( $method, get_class_methods( $product ) ) ) {
  print $product->$method(); // invoke the method
}
if ( is_callable( array( $product, $method) ) ) {
  print $product->$method(); // invoke the method
}
if ( method_exists( $product, $method ) ) {
  print $product->$method(); // invoke the method
}
print_r( get_class_vars( 'CdProduct' ) );
if ( is_subclass_of( $product, 'ShopProduct' ) ) {
  print "CdProduct is a subclass of ShopProduct\n";
}
if ( is_subclass_of( $product, 'incidental' ) ) {
  print "CdProduct is a subclass of incidental\n";
}
if ( in_array( 'incidental', class_implements( $product )) ) {
  print "CdProduct is an interface of incidental\n";
}
?>

output:

title
title
title
title
Array
(
  [coverUrl] =>
)
CdProduct is a subclass of ShopProduct
CdProduct is a subclass of incidental
CdProduct is an interface of incidental

__call方法

<?php
class OtherShop {
  function thing() {
    print "thing\n";
  }
  function andAnotherthing() {
    print "another thing\n";
  }
}
class Delegator {
  private $thirdpartyShop;
  function __construct() {
    $this->thirdpartyShop = new OtherShop();
  }
  function __call( $method, $args ) { // 当调用未命名方法时执行call方法
    if ( method_exists( $this->thirdpartyShop, $method ) ) {
      return $this->thirdpartyShop->$method( );
    }
  }
}
$d = new Delegator();
$d->thing();
?>

output:

thing

传参使用

<?php
class OtherShop {
  function thing() {
    print "thing\n";
  }
  function andAnotherthing( $a, $b ) {
    print "another thing ($a, $b)\n";
  }
}
class Delegator {
  private $thirdpartyShop;
  function __construct() {
    $this->thirdpartyShop = new OtherShop();
  }
  function __call( $method, $args ) {
    if ( method_exists( $this->thirdpartyShop, $method ) ) {
      return call_user_func_array(
            array( $this->thirdpartyShop,
              $method ), $args );
    }
  }
}
$d = new Delegator();
$d->andAnotherThing( "hi", "hello" );
?>

output:

another thing (hi, hello)

反射API

fullshop.php

<?php
class ShopProduct {
  private $title;
  private $producerMainName;
  private $producerFirstName;
  protected $price;
  private $discount = 0;
  public function __construct(  $title, $firstName,
              $mainName, $price ) {
    $this->title       = $title;
    $this->producerFirstName = $firstName;
    $this->producerMainName = $mainName;
    $this->price       = $price;
  }
  public function getProducerFirstName() {
    return $this->producerFirstName;
  }
  public function getProducerMainName() {
    return $this->producerMainName;
  }
  public function setDiscount( $num ) {
    $this->discount=$num;
  }
  public function getDiscount() {
    return $this->discount;
  }
  public function getTitle() {
    return $this->title;
  }
  public function getPrice() {
    return ($this->price - $this->discount);
  }
  public function getProducer() {
    return "{$this->producerFirstName}".
        " {$this->producerMainName}";
  }
  public function getSummaryLine() {
    $base = "{$this->title} ( {$this->producerMainName}, ";
    $base .= "{$this->producerFirstName} )";
    return $base;
  }
}
class CdProduct extends ShopProduct {
  private $playLength = 0;
  public function __construct(  $title, $firstName,
              $mainName, $price, $playLength=78 ) {
    parent::__construct(  $title, $firstName,
                $mainName, $price );
    $this->playLength = $playLength;
  }
  public function getPlayLength() {
    return $this->playLength;
  }
  public function getSummaryLine() {
    $base = parent::getSummaryLine();
    $base .= ": playing time - {$this->playLength}";
    return $base;
  }
}
class BookProduct extends ShopProduct {
  private $numPages = 0;
  public function __construct(  $title, $firstName,
              $mainName, $price, $numPages ) {
    parent::__construct(  $title, $firstName,
                $mainName, $price );
    $this->numPages = $numPages;
  }
  public function getNumberOfPages() {
    return $this->numPages;
  }
  public function getSummaryLine() {
    $base = parent::getSummaryLine();
    $base .= ": page count - {$this->numPages}";
    return $base;
  }
  public function getPrice() {
    return $this->price;
  }
}
/*
$product1 = new CdProduct("cd1", "bob", "bobbleson", 4, 50 );
print $product1->getSummaryLine()."\n";
$product2 = new BookProduct("book1", "harry", "harrelson", 4, 30 );
print $product2->getSummaryLine()."\n";
*/
?>
<?php
require_once "fullshop.php";
$prod_class = new ReflectionClass( 'CdProduct' );
Reflection::export( $prod_class );
?>

output:

Class [ <user> class CdProduct extends ShopProduct ] {
 @@ D:\xampp\htdocs\popp-code\5\fullshop.php 53-73
 - Constants [0] {
 }
 - Static properties [0] {
 }
 - Static methods [0] {
 }
 - Properties [2] {
  Property [ <default> private $playLength ]
  Property [ <default> protected $price ]
 }
 - Methods [10] {
  Method [ <user, overwrites ShopProduct, ctor> public method __construct ] {
   @@ D:\xampp\htdocs\popp-code\5\fullshop.php 56 - 61
   - Parameters [5] {
    Parameter #0 [ <required> $title ]
    Parameter #1 [ <required> $firstName ]
    Parameter #2 [ <required> $mainName ]
    Parameter #3 [ <required> $price ]
    Parameter #4 [ <optional> $playLength = 78 ]
   }
  }
  Method [ <user> public method getPlayLength ] {
   @@ D:\xampp\htdocs\popp-code\5\fullshop.php 63 - 65
  }
  Method [ <user, overwrites ShopProduct, prototype ShopProduct> public method getSummaryLine ] {
   @@ D:\xampp\htdocs\popp-code\5\fullshop.php 67 - 71
  }
  Method [ <user, inherits ShopProduct> public method getProducerFirstName ] {
   @@ D:\xampp\htdocs\popp-code\5\fullshop.php 17 - 19
  }
  Method [ <user, inherits ShopProduct> public method getProducerMainName ] {
   @@ D:\xampp\htdocs\popp-code\5\fullshop.php 21 - 23
  }
  Method [ <user, inherits ShopProduct> public method setDiscount ] {
   @@ D:\xampp\htdocs\popp-code\5\fullshop.php 25 - 27
   - Parameters [1] {
    Parameter #0 [ <required> $num ]
   }
  }
  Method [ <user, inherits ShopProduct> public method getDiscount ] {
   @@ D:\xampp\htdocs\popp-code\5\fullshop.php 29 - 31
  }
  Method [ <user, inherits ShopProduct> public method getTitle ] {
   @@ D:\xampp\htdocs\popp-code\5\fullshop.php 33 - 35
  }
  Method [ <user, inherits ShopProduct> public method getPrice ] {
   @@ D:\xampp\htdocs\popp-code\5\fullshop.php 37 - 39
  }
  Method [ <user, inherits ShopProduct> public method getProducer ] {
   @@ D:\xampp\htdocs\popp-code\5\fullshop.php 41 - 44
  }
 }
}

点评:把类看的透彻的一塌糊涂,比var_dump强多了。哪些属性,继承了什么类。类中的方法哪些是自己的,哪些是重写的,哪些是继承的,一目了然。

查看类数据

<?php
require_once("fullshop.php");
function classData( ReflectionClass $class ) {
 $details = "";
 $name = $class->getName();
 if ( $class->isUserDefined() ) {
  $details .= "$name is user defined\n";
 }
 if ( $class->isInternal() ) {
  $details .= "$name is built-in\n";
 }
 if ( $class->isInterface() ) {
  $details .= "$name is interface\n";
 }
 if ( $class->isAbstract() ) {
  $details .= "$name is an abstract class\n";
 }
 if ( $class->isFinal() ) {
  $details .= "$name is a final class\n";
 }
 if ( $class->isInstantiable() ) {
  $details .= "$name can be instantiated\n";
 } else {
  $details .= "$name can not be instantiated\n";
 }
 return $details;
}
$prod_class = new ReflectionClass( 'CdProduct' );
print classData( $prod_class );
?>

output:

CdProduct is user defined
CdProduct can be instantiated

查看方法数据

<?php
require_once "fullshop.php";
$prod_class = new ReflectionClass( 'CdProduct' );
$methods = $prod_class->getMethods();
foreach ( $methods as $method ) {
 print methodData( $method );
 print "\n----\n";
}
function methodData( ReflectionMethod $method ) {
 $details = "";
 $name = $method->getName();
 if ( $method->isUserDefined() ) {
  $details .= "$name is user defined\n";
 }
 if ( $method->isInternal() ) {
  $details .= "$name is built-in\n";
 }
 if ( $method->isAbstract() ) {
  $details .= "$name is abstract\n";
 }
 if ( $method->isPublic() ) {
  $details .= "$name is public\n";
 }
 if ( $method->isProtected() ) {
  $details .= "$name is protected\n";
 }
 if ( $method->isPrivate() ) {
  $details .= "$name is private\n";
 }
 if ( $method->isStatic() ) {
  $details .= "$name is static\n";
 }
 if ( $method->isFinal() ) {
  $details .= "$name is final\n";
 }
 if ( $method->isConstructor() ) {
  $details .= "$name is the constructor\n";
 }
 if ( $method->returnsReference() ) {
  $details .= "$name returns a reference (as opposed to a value)\n";
 }
 return $details;
}
?>

output:

__construct is user defined
__construct is public
__construct is the constructor
----
getPlayLength is user defined
getPlayLength is public
----
getSummaryLine is user defined
getSummaryLine is public
----
getProducerFirstName is user defined
getProducerFirstName is public
----
getProducerMainName is user defined
getProducerMainName is public
----
setDiscount is user defined
setDiscount is public
----
getDiscount is user defined
getDiscount is public
----
getTitle is user defined
getTitle is public
----
getPrice is user defined
getPrice is public
----
getProducer is user defined
getProducer is public

获取构造函数参数情况

<?php
require_once "fullshop.php";
$prod_class = new ReflectionClass( 'CdProduct' );
$method = $prod_class->getMethod( "__construct" );
$params = $method->getParameters();
foreach ( $params as $param ) {
  print argData( $param )."\n";
}
function argData( ReflectionParameter $arg ) {
 $details = "";
 $declaringclass = $arg->getDeclaringClass();
 $name = $arg->getName();
 $class = $arg->getClass();
 $position = $arg->getPosition();
 $details .= "\$$name has position $position\n";
 if ( ! empty( $class ) ) {
  $classname = $class->getName();
  $details .= "\$$name must be a $classname object\n";
 }
 if ( $arg->isPassedByReference() ) {
  $details .= "\$$name is passed by reference\n";
 }
 if ( $arg->isDefaultValueAvailable() ) {
  $def = $arg->getDefaultValue();
  $details .= "\$$name has default: $def\n";
 }
 if ( $arg->allowsNull() ) {
  $details .= "\$$name can be null\n";
 }
 return $details;
}
?>

output:

$title has position 0
$title can be null
$firstName has position 1
$firstName can be null
$mainName has position 2
$mainName can be null
$price has position 3
$price can be null
$playLength has position 4
$playLength has default: 78
$playLength can be null

希望本文所述对大家PHP程序设计有所帮助。

PHP 相关文章推荐
php实现mysql数据库备份类
Mar 20 PHP
通俗易懂的php防注入代码
Apr 07 PHP
PHP中运用jQuery的Ajax跨域调用实现代码
Feb 21 PHP
Zend的Registry机制的使用说明
May 02 PHP
php读取纯真ip数据库使用示例
Jan 26 PHP
9段PHP实用功能的代码推荐
Oct 14 PHP
PHP callback函数使用方法和注意事项
Jan 23 PHP
DEDECMS首页调用图片集里的多张图片
Jun 05 PHP
php实现CSV文件导入和导出
Oct 24 PHP
PHP实现的简单分页类及用法示例
May 06 PHP
php array_udiff_assoc 计算两个数组的差集实例
Nov 12 PHP
PHP实现微信JS-SDK接口选择相册及拍照并上传的方法
Dec 05 PHP
PHP面向对象程序设计之对象生成方法详解
Dec 02 #PHP
PHP面向对象程序设计组合模式与装饰模式详解
Dec 02 #PHP
PHP与jquery实时显示网站在线人数实例详解
Dec 02 #PHP
谈谈php对接芝麻信用踩的坑
Dec 01 #PHP
PHP自定义函数获取汉字首字母的方法
Dec 01 #PHP
phpmailer绑定邮箱的实现方法
Dec 01 #PHP
thinkPHP实现多字段模糊匹配查询的方法
Dec 01 #PHP
You might like
php ctype函数中文翻译和示例
2014/03/21 PHP
php常用正则函数实例小结
2016/12/29 PHP
PHP PDO数据库操作预处理与注意事项
2019/03/16 PHP
jQuery图片滚动图片的效果(另类实现)
2013/06/02 Javascript
解析javascript 浏览器关闭事件
2013/07/08 Javascript
offsetHeight在OnLoad中获取为0的现象
2013/07/22 Javascript
JavaScript中for..in循环陷阱介绍
2013/11/12 Javascript
node.js中的buffer.toString方法使用说明
2014/12/14 Javascript
JavaScript 浏览器对象模型BOM使用介绍
2015/04/13 Javascript
原生js实现移动开发轮播图、相册滑动特效
2015/04/17 Javascript
jQuery实现弹出窗口中切换登录与注册表单
2015/06/05 Javascript
纯js代码实现未知宽高的元素在指定元素中垂直水平居中显示
2015/09/12 Javascript
jQuery中通过ajax调用webservice传递数组参数的问题实例详解
2016/05/20 Javascript
JS函数多个参数默认值指定方法分析
2016/11/28 Javascript
bootstrap模态框垂直居中效果
2016/12/03 Javascript
详解javascript中对数据格式化的思考
2017/01/23 Javascript
vue货币过滤器的实现方法
2017/04/01 Javascript
JS通过调用微信API实现微信支付功能的方法示例
2017/06/29 Javascript
三分钟教你用Node做一个微信哄女友(基友)神器(面向小白)
2019/06/21 Javascript
vue监听滚动事件的方法
2020/12/21 Vue.js
学习 Vue.js 遇到的那些坑
2021/02/02 Vue.js
python用来获得图片exif信息的库实例分析
2015/03/16 Python
Python 中 Virtualenv 和 pip 的简单用法详解
2017/08/18 Python
10 分钟快速入门 Python3的教程
2019/01/29 Python
Python3使用TCP编写一个简易的文件下载器功能
2019/05/08 Python
python安装requests库的实例代码
2019/06/25 Python
PYTHON如何读取和写入EXCEL里面的数据
2019/10/28 Python
Python @property原理解析和用法实例
2020/02/11 Python
解决jupyter notebook显示不全出现框框或者乱码问题
2020/04/09 Python
Origins悦木之源英国官网:雅诗兰黛集团高端植物护肤品牌
2017/11/06 全球购物
介绍一下OSI七层模型
2012/07/03 面试题
医学检验专业自荐信
2014/09/18 职场文书
检讨书怎么写
2015/05/07 职场文书
如何写好闭幕词
2019/04/02 职场文书
python3实现无权最短路径的方法
2021/05/12 Python
Java获取字符串编码格式实现思路
2022/09/23 Java/Android