Home  >  Article  >  php教程  >  Detailed explanation of PHP object-oriented programming and reflection API

Detailed explanation of PHP object-oriented programming and reflection API

高洛峰
高洛峰Original
2016-12-30 10:14:231323browse

本文实例讲述了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 &#39;Exception&#39; with message &#39;No such class as tasks\Task&#39;
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 ) == &#39;CdProduct&#39; ) {
  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( &#39;CdProduct&#39; ) );
?>

   

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( &#39;CdProduct&#39; ) );
if ( is_subclass_of( $product, &#39;ShopProduct&#39; ) ) {
  print "CdProduct is a subclass of ShopProduct\n";
}
if ( is_subclass_of( $product, &#39;incidental&#39; ) ) {
  print "CdProduct is a subclass of incidental\n";
}
if ( in_array( &#39;incidental&#39;, 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( &#39;CdProduct&#39; );
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( &#39;CdProduct&#39; );
print classData( $prod_class );
?>

   

output:

CdProduct is user defined
CdProduct can be instantiated

查看方法数据

<?php
require_once "fullshop.php";
$prod_class = new ReflectionClass( &#39;CdProduct&#39; );
$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( &#39;CdProduct&#39; );
$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面向对象程序设计之类与反射API详解相关文章请关注PHP中文网!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn