php里面用魔术方法和匿名函数闭包函数动态的给类里面添加方法
1.认识 __set (在给不可访问属性赋值时,__set() 会被调用)
也就是说你再访问一个类里面没有的属性,会出发这个方法
class A{
private $aa = '11';
public function __set($name, $value)
{
$this->$name = $value;
}
}
$a = new A();
$a->name = 'name';
echo $a->name;
2.认识 __set (在对象中调用一个不可访问方法时,__call() 会被调用。)
class B{
private $bb = '22';
public function __call($name, $arguments)
{
echo $name;
var_dump($arguments);
}
}
$b = new B();
$b->names();
3.动态添加方法
class B{
private $bb = '22';
public function __set($name, $value)
{
$this->$name = $value;
}
public function __call($name, $arguments)
{//注意:没用形参$name
return call_user_func($this->$name,$arguments);//通过这个把属性的匿名方法加进来 注意:$arguments 是一个数组
}
}
$b = new B();
$b->names = function(){echo 'this is a fun ';};
$b->names();
//这时候B类里面已经有一个 属性name 指向一个匿名方法
//怎么运行呢? $b->name() 错误因为类里面没有这个方法 ---这个错误可以触发__call()魔术方法
//这时候还不能在 匿名函数 中用B类里面的 属性
4.动态加方法之,让闭包函数也能操作类里面的属性 参考(http://php.net/manual/zh/closure.bindto.php)
class C{
private $cc = '33';
public function __set($name, $value)
{
//$this->$name = $value; //(和上面例子比较 就改动了这个)
$this->$name = $value->bindTo($this,$this);//复制当前闭包函数,绑定指定的$this作用域对象,这样匿名函数就可以访问类的属性值了
}
public function __call($name, $arguments)
{
return call_user_func($this->$name,$arguments);
}
}
$c = new C();
$c->username = function ($strs){
var_dump($strs);//这里其实是 call_user_func的$arguments传过来的是数组
$this->cc=4;//可以操作作用于的属性值
return '111';
};
echo $c->username('字符串');
一个完整的例子:
/**
* 给类动态添加新方法
*
* @author fantasy
*/
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 fantasy
*/
class Animal {
use DynamicTrait;
private $dog = '汪汪队';
}
$animal = new Animal;
// 往动物类实例中添加一个方法获取实例的私有属性$dog
$animal->getdog = function() {
return $this->dog;
};
echo $animal->getdog();//输出 汪汪队
动态给类里面加方法,就是把一个闭包函数通过__set和__call结合call_user_func()等方法,加入进去,
为了让匿名函数或闭包函数可以访问类的属性值,需要结合Closure类的Closure::bindTo (复制当前包对象,绑定到指定this作用域)
参考:http://www.cnblogs.com/fps2tao/p/8727248.html
php里面用魔术方法和匿名函数闭包函数动态的给类里面添加方法的更多相关文章
- 速战速决 (3) - PHP: 函数基础, 函数参数, 函数返回值, 可变函数, 匿名函数, 闭包函数, 回调函数
[源码下载] 速战速决 (3) - PHP: 函数基础, 函数参数, 函数返回值, 可变函数, 匿名函数, 闭包函数, 回调函数 作者:webabcd 介绍速战速决 之 PHP 函数基础 函数参数 函 ...
- python 函数--闭包函数
一.闭包函数: 在一个外函数中定义一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用. 二.实例: def outer(a): #外函数 b = 10 #临时变量 def i ...
- PHP函数(六)-匿名函数(闭包函数)
匿名函数能够临时创建一个没有名称的函数,常用作回调函数参数的值 <?php $test = function($a){ echo "Hello,".$a; }; $test( ...
- python 内嵌函数, 闭包, 函数装饰器
一. 函数内嵌 闭包 在python中,函数可以作为返回值, 可以给变量赋值. 在python中, 内置函数必须被显示的调用, 否则不会执行. #!/usr/bin/env python #-*- ...
- ios开发runtime学习三:动态添加方法(实际应用少,面试)
#import "ViewController.h" #import "Person.h" /* 1: Runtime(动态添加方法):OC都是懒加载机制,只要 ...
- 如何为jquery添加方法
以下内容引自一位网友的帖子: jQuery插件的开发包括两种: 一种是类级别的插件开发,即给jQuery添加新的全局函数,相当于给jQuery类本身添加方法.jQuery的全局函数就是属于jQuery ...
- 快速上手Runtime(四)之动态添加方法
如果一个类方法非常多,加载类到内存的时候也比较耗费资源,可以使用动态给某个类,添加方法解决.做到优化内存,节省资源的效果. // // Person.m // ResolveInstanceMetho ...
- JavaScript匿名自执行函数~function(){}
原博客:https://blog.csdn.net/yaojxing/article/details/72784774 1.匿名函数的常见场景 js中的匿名函数是一种很常见的函数类型,比较常见的场景: ...
- php的匿名函数和闭包函数
php的匿名函数和闭包函数 tags: 匿名函数 闭包函数 php闭包函数 php匿名函数 function use 引言:匿名函数和闭包函数都不是特别高深的知识,但是很多刚入门的朋友却总是很困惑,因 ...
随机推荐
- UVA 1151 Buy or Build MST(最小生成树)
题意: 在平面上有n个点,要让所有n个点都连通,所以你要构造一些边来连通他们,连通的费用等于两个端点的欧几里得距离的平方.另外还有q个套餐,可以购买,如果你购买了第i个套餐,该套餐中的所有结点将变得相 ...
- Python_Tips[0] -> 关于 import
关于 import 1 import import可用于导入一个Python的标准模块,包括.py文件或带有__init__.py的文件目录. 在Python中,import一个模块后,若再次impo ...
- 消息队列集群kafka安装配置
1. 下载wget http://mirror.rise.ph/apache/kafka/0.11.0.0/kafka_2.12-0.11.0.0.tgz2. 安装tar xf kafka_2.12- ...
- LINUX 下mysql导出数据、表结构
1.首先要确认mysqldump命令所在路径 例如,我的在:/usr/bin/ 下 [root@sf105113 bin]# which mysqldump /usr/bin/mysqldump 2. ...
- java的几个特性
前言 本文主要介绍java语言的三个特性:类型协变和逆变,动态代理和静态代理,注解. 协变和逆变 借用Treant的博文,逆变与协变用来描述类型转换(type transformation)后的继承关 ...
- uVa 12563 Jin Ge Jin Qu
分析可知,虽然t<109,但是总曲目时间大于t,实际上t不会超过180*n+678.此问题涉及到两个目标信息,首先要求曲目数量最多,在此基础上要求所唱的时间尽量长.可以定义 状态dp[i][j] ...
- Android 常驻与很驻型广播的差别,及ListView优化,Android新手基本知识巩固
1.常驻型广播 常驻型广播,当你的应用程序关闭了,假设有广播信息来,你写的广播接收器相同的能接受到. 他的注冊方式就是在你的应用程序中的AndroidManifast.xml进行注冊. 通常说这样 ...
- redis学习笔记——入门
基本安装和用法:http://www.tuicool.com/articles/QzMRNb Redis如何通过本机客户端访问远程服务器段:http://blog.sina.com.cn/s/blog ...
- Effective C++ 条款17
以独立语句将newed对象置入智能指针 本节我们须要学习的知识核心是注意编译器在同一语句中,调用次序具有不确定性,不同语句中,调用次序确定. 上面的话什么意思? 请看下面代码: int priorit ...
- Linux 命令 indent 用法
此命令用于调整C源码的格式. 在LKD中的例子: indent -kr -i8 -ts8 -sob -l80 -ss -bs -psl filename 参数解释如下: -i :设置缩进的格数 - ...