colsure php_PHP中Closure类详解

本文主要和大家分享PHP中Closure类详解,PHP Closure 类是用于代表匿名函数的类,匿名函数(在 PHP 5.3 中被引入)会产生这个类型的对象,Closure类摘要如下:Closure {

__construct ( void )

public static Closure bind (Closure $closure , object $newthis [, mixed $newscope = 'static' ])

public Closure bindTo (object $newthis [, mixed $newscope = 'static' ])

}

方法说明:

Closure::__construct — 用于禁止实例化的构造函数

Closure::bind — 复制一个闭包,绑定指定的$this对象和类作用域。

Closure::bindTo — 复制当前闭包对象,绑定指定的$this对象和类作用域。

除了此处列出的方法,还有一个 __invoke 方法。这是为了与其他实现了 __invoke()魔术方法 的对象保持一致性,但调用闭包对象的过程与它无关。

下面将介绍Closure::bind和Closure::bindTo。

Closure::bind是Closure::bindTo的静态版本,其说明如下:public static Closure bind (Closure $closure , object $newthis [, mixed $newscope = 'static' ])

closure表示需要绑定的闭包对象。

newthis表示需要绑定到闭包对象的对象,或者NULL创建未绑定的闭包。

newscope表示想要绑定给闭包的类作用域,可以传入类名或类的示例,默认值是 'static', 表示不改变。

该方法成功时返回一个新的 Closure 对象,失败时返回FALSE。

例子说明:<?php

/**

* 复制一个闭包,绑定指定的$this对象和类作用域。

*

* @author 疯狂老司机

*/

class Animal {

private static $cat = "cat";

private $dog = "dog";

public $pig = "pig";

}

/*

* 获取Animal类静态私有成员属性

*/

$cat = static function() {

return Animal::$cat;

};

/*

* 获取Animal实例私有成员属性

*/

$dog = function() {

return $this->dog;

};

/*

* 获取Animal实例公有成员属性

*/

$pig = function() {

return $this->pig;

};

$bindCat = Closure::bind($cat, null, new Animal());// 给闭包绑定了Animal实例的作用域,但未给闭包绑定$this对象

$bindDog = Closure::bind($dog, new Animal(), 'Animal');// 给闭包绑定了Animal类的作用域,同时将Animal实例对象作为$this对象绑定给闭包

$bindPig = Closure::bind($pig, new Animal());// 将Animal实例对象作为$this对象绑定给闭包,保留闭包原有作用域

echo $bindCat(),'
';// 根据绑定规则,允许闭包通过作用域限定操作符获取Animal类静态私有成员属性

echo $bindDog(),'
';// 根据绑定规则,允许闭包通过绑定的$this对象(Animal实例对象)获取Animal实例私有成员属性

echo $bindPig(),'
';// 根据绑定规则,允许闭包通过绑定的$this对象获取Animal实例公有成员属性

?>

输出:

cat

dog

pig

Closure::bindTo — 复制当前闭包对象,绑定指定的$this对象和类作用域,其说明如下:public Closure Closure::bindTo (object $newthis [, mixed $newscope = 'static' ])

newthis表示绑定给闭包对象的一个对象,或者NULL来取消绑定。

newscope表示关联到闭包对象的类作用域,可以传入类名或类的示例,默认值是 'static', 表示不改变。

该方法创建并返回一个闭包对象,它与当前对象绑定了同样变量,但可以绑定不同的对象,也可以绑定新的类作用域。绑定的对象决定了返回的闭包对象中的$this的取值,类作用域决定返回的闭包对象能够调用哪些方法,也就是说,此时$this可以调用的方法,与newscope类作用域相同。

例子1:<?php

function __autoload($class) {

require_once "$class.php";

}

$template = new Template;

$template->render(new Article, 'tpl.php');

?>

Template.php 模板类<?php

/**

* 模板类,用于渲染输出

*

* @author 疯狂老司机

*/

class Template{

/**

* 渲染方法

*

* @access public

* @param obj 信息类

* @param string 模板文件名

*/

public function render($context, $tpl){

$closure = function($tpl){

ob_start();

include $tpl;

return ob_end_flush();

};

$closure = $closure->bindTo($context, $context);

$closure($tpl);

}

}

Article.php 信息类<?php

/**

* 文章信息类

*

* @author 疯狂老司机

*/

class Article{

private $title = "这是文章标题";

private $content = "这是文章内容";

}

tpl.php 模板文件

<?php echo $this->title;?>

<?php echo $this->content;?>

运行时确保以上文件位于同级目录。

输出:

这是文章标题

这是文章内容

例子2:<?php

/**

* 给类动态添加新方法

*

* @author 疯狂老司机

*/

trait DynamicTrait {

/**

* 自动调用类中存在的方法

*/

public function __call($name, $args) {

if(is_callable($this->$name)){

return call_user_func($this->$name, $args);

}else{

throw new \RuntimeException("Method {$name} does not exist");

}

}

/**

* 添加方法

*/

public function __set($name, $value) {

$this->$name = is_callable($value)?

$value->bindTo($this, $this):

$value;

}

}

/**

* 只带属性不带方法动物类

*

* @author 疯狂老司机

*/

class Animal {

use DynamicTrait;

private $dog = 'dog';

}

$animal = new Animal;

// 往动物类实例中添加一个方法获取实例的私有属性$dog

$animal->getdog = function() {

return $this->dog;

};

echo $animal->getdog();

?>

输出:

dog

例子3:<?php

/**

* 一个基本的购物车,包括一些已经添加的商品和每种商品的数量

*

* @author 疯狂老司机

*/

class Cart {

// 定义商品价格

const PRICE_BUTTER = 1.00;

const PRICE_MILK = 3.33;

const PRICE_EGGS = 8.88;

protected $products = array();

/**

* 添加商品和数量

*

* @access public

* @param string 商品名称

* @param string 商品数量

*/

public function add($item, $quantity) {

$this->products[$item] = $quantity;

}

/**

* 获取单项商品数量

*

* @access public

* @param string 商品名称

*/

public function getQuantity($item) {

return isset($this->products[$item]) ? $this->products[$item] : FALSE;

}

/**

* 获取总价

*

* @access public

* @param string 税率

*/

public function getTotal($tax) {

$total = 0.00;

$callback = function ($quantity, $item) use ($tax, &$total) {

$pricePerItem = constant(__CLASS__ . "::PRICE_" . strtoupper($item));

$total += ($pricePerItem * $quantity) * ($tax + 1.0);

};

array_walk($this->products, $callback);

return round($total, 2);;

}

}

$my_cart = new Cart;

// 往购物车里添加商品及对应数量

$my_cart->add('butter', 10);

$my_cart->add('milk', 3);

$my_cart->add('eggs', 12);

// 打出出总价格,其中有 5% 的销售税.

echo $my_cart->getTotal(0.05);

?>

输出:

132.88

补充说明:闭包可以使用USE关键连接外部变量。

总结:合理使用闭包能使代码更加简洁和精炼。

相关推荐:

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值