一.依据闭包实现一个容器

class Di
{
private $factory; public function set($id, $value)
{
$this->factory[$id] = $value;
} public function get($id)
{
$val = $this->factory[$id];
return $val();//如果不加括号,仅仅返回的是闭包类,并不是User实例
}
} class User
{
private $username; public function __construct($username = '')
{
$this->username = $username;
} public function getUserName()
{
return $this->username;
}
} $di = new Di(); // 在此使用了闭包,所以实际上并不会实例化User类,只有在后面get的时候才会实例化
$di->set('a', function(){
return new User('张三');
}); var_dump($di->get('a')->getUserName());

  

二.使用闭包作为回调

class Cart
{
CONST PRICE_BUTTER = 1.0;
CONST PRICE_MILK = 5.05; protected $products = []; public function add($product, $quantity)
{
$this->products[$product] = $quantity;
} public function getQuantity($product)
{
return isset($this->products[$product]) ? $this->products[$product]: false;
} public function getTotal($tax)
{
$total = 0.00;
$callback = function($quantity, $product) use ($tax, &$total) {
$priceItem = constant(__CLASS__ . '::PRICE_' . strtoupper($product));
$total += ($priceItem * $quantity) * ($tax + 1.0);
}; array_walk($this->products, $callback);
return round($total, 2);
}
} $cart = new Cart();
$cart->add('butter', 1);
$cart->add('milk', 5); echo $cart->getTotal(0.05);

  

三.使用闭包函数调用类中方法

class Grid
{
protected $builder;
protected $attribute; public function __construct(Closure $builler)
{
$this->builder = $builler;
} public function addColumn($name, $value)
{
$this->attribute[$name] = $value;
return $this;
} public function build()
{
// 这儿回调闭包函数,参数为this
call_user_func($this->builder, $this);
} public function __toString()
{
$this->build(); $str = '';
$call = function($val, $key) use(&$str) {
$str .= "$key=>$val;";
};
array_walk($this->attribute, $call); return $str;
}
} $grid = new Grid(
// 传入闭包函数,带参数
function($grid) {
$grid->addColumn('key1', 'val1');
$grid->addColumn('key2', 'val2');
}
); echo $grid;

  

闭包在对象中的一个典型使用场景就是留出一个方法给调用者,让调用者自主决定或组装数据.
如下例:让调用者决定如何组装或显示info.

class CalledClass {
private $name;
private $age;
private $info; public function __construct($name, $age, Closure $callable)
{
$this->name = $name;
$this->age = $age;
call_user_func($callable, $this);
// 这相当于
// $callable($this);
} public function setInfo($info)
{
$this->info = $info;
} public function getInfo()
{
echo $this->info;
} /**
* @return mixed
*/
public function getName()
{
return $this->name;
} /**
* @return mixed
*/
public function getAge()
{
return $this->age;
} } $c = new CalledClass('php', 10, function (CalledClass $c) {
echo $c->getAge() . $c->getName();
$c->setInfo($c->getAge() . $c->getName());
}); echo $c->getInfo();

  

php闭包使用例子的更多相关文章

  1. javascript闭包学习例子

    javascript中的闭包个很让人头疼的概念.总结一下 闭包是指有权访问一个函数作用域中的变量的函数.创建闭包最常见的方式,是在一个函数内部创建另一个函数,用return返回出去. 使用闭包可能造成 ...

  2. javascript 闭包理解例子

    function Jquery(){ this.name = 'ysr'; this.sex = 'man'; return { x: this, age : 26 } } var b = new J ...

  3. JavaScript 闭包的例子

    例子出自<<JavaScript权威指南>>, 加上个人的理解和总结, 欢迎交流! /********************************************* ...

  4. python闭包小例子

    ------------------ 首先根据实例, 体会一下闭包的效果 ------------------ 定义闭包: def foo(x): a = [0] def bar(y): a[0] = ...

  5. 一段关于python 闭包的例子

    >>> def counter(a=0): ... count = a ... def incr(): ... b = 1 + count ... return b ... retu ...

  6. js闭包原理与例子[转]

    闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 一.闭包原理: 一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域 ...

  7. 让你分分钟学会Javascript中的闭包

    Javascript中的闭包 前面的话: 闭包,是 javascript 中重要的一个概念,对于初学者来讲,闭包是一个特别抽象的概念,特别是ECMA规范给的定义,如果没有实战经验,你很难从定义去理解它 ...

  8. 【javascript】作用域和闭包浅析

    作用域 分全局作用域和局部作用域 全局作用域:函数外部定义的变量,可以被整个program的各成员参照利用. 局部作用域:函数内部定义的变量,仅供该函数的各成员参照利用. var val=1; //全 ...

  9. C# 闭包

    1. 首先要说明的是, delegate 被编译器 编译成一个class, 所以才能传来传去(具体参考 <CLR via C#>第四版), 所以 Action.Func也是如此 2. 在C ...

随机推荐

  1. bzoj3969 [WF2013]Low Power

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3969 [题解] 二分答案x,贪心选取,如果选取了i个,有j对,那么要满足i<=2*j* ...

  2. jQuery选择器总结(重要)

    jQuery 的选择器可谓之强大无比,这里简单地总结一下常用的元素查找方法 $("#myELement") 选择id值等于myElement的元素,id值不能重复在文档中只能有一个 ...

  3. matlab7 + sqlitejdbc-v056.jar出现错误

    conn=database('data.db','','','org.sqlite.JDBC','jdbc:sqlite:C:/MATLAB7/work/del_man_voice_from_wave ...

  4. MFC 菜单操作

    在CMainFrame中OnCreate函数中添加下列:(注意在return(0)前添加) 在文件,新建前打钩 法1: GetMenu()->GetSubMenu(0)->CheckMen ...

  5. RMQ-ST算法

    1068 : RMQ-ST算法 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho在美国旅行了相当长的一段时间之后,终于准备要回国啦!而在回国之前,他们准备去 ...

  6. hdu 5108(数论-整数分解)

    Alexandra and Prime Numbers Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (J ...

  7. [BZOJ3211]花神游历各国&&[BZOJ3038] 上帝造题的七分钟2 树状数组+并查集

    3211: 花神游历各国 Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 4057  Solved: 1480[Submit][Status][Discu ...

  8. 获取父窗口iframe方法

    在页面中,有个iframe,基于这个iframe,弹出了个窗口,这个窗口在关闭的时候需要操作iframe里的元素. 做法是 window.top.document.getElementById(&qu ...

  9. html5进阶之canvas图像基础

    1.首先还是使用之前讲过的Image()函数来预加载图像. 在调用图像之前,需创建一个事件监听器,为其保证图像已经正确的加载. 如下图: 监听图片已经正确加载 2.把图像显示在画布上面,这里将不再使用 ...

  10. 关于asp.net中gridview的问题,关于footer,16aspx上下的英语交流网程序,管理员的添加和修改有问题

    css部分 这是添加用户的方法 但是A.AdminName 和后面的A.取到的都是空值protected void GridView1_RowCommand(object sender,GridVie ...