扒了扒之前的云笔记,发现了一些很有意思的笔记,下面是一段php程序,可以动态的添加成员函数以及成员变量。是之前在php手册上看到的,感觉很有意思,分享给大家。
//整个类同过闭包以及魔法方法动态的添加了一系列的全局变量以及函数,在编程过程中对扩展一个方法是非常有用的
//构造方法中表示在构造的时候可以传入一个数组,同事数组的键值为属性名,值为属性值
//__call方法表示对没有的方法时调用此方法
<?php
//定义一个类
class stdObject {
public function __construct(array $arguments = array()) {
if (!empty($arguments)) {
foreach ($arguments as $property => $argument) {
$this->{$property} = $argument;
}
}
}
//魔法方法,当没有调用的函数是回调此方法
public function __call($method, $arguments) {
//将对象本身作为参数的第一个值合并到参数中
$arguments = array_merge(array("stdObject" => $this), $arguments); // Note: method argument 0 will always referred to the main class ($this).
//判断是否存在调用的模块,如果存在判断是否可以调用,如果可以调用,将模块(函数)名,和参数通过call_user_func_array()去执行函数
if (isset($this->{$method}) && is_callable($this->{$method})) {
return call_user_func_array($this->{$method}, $arguments);
} else {
throw new Exception("Fatal error: Call to undefined method stdObject::{$method}()");
}
}
}
// Usage.
$obj = new stdObject();
//定义类中的全局变量
$obj->name = "Nick";
$obj->surname = "Doe";
$obj->age = 20;
$obj->adresse = null;
//定义的一个闭包函数
$obj->getInfo = function($stdObject) { // $stdObject referred to this object (stdObject).
echo $stdObject->name . " " . $stdObject->surname . " have " . $stdObject->age . " yrs old. And live in " . $stdObject->adresse;
};
$func = "setAge";
$obj->{$func} = function($stdObject, $age) { // $age is the first parameter passed when calling this method.
$stdObject->age = $age;
};
//调用闭包函数
$obj->setAge(24); // Parameter value 24 is passing to the $age argument in method 'setAge()'.
// Create dynamic method. Here i'm generating getter and setter dynimically
// Beware: Method name are case sensitive.
//循环取出对象中的函数/变量名,分别动态生成对应的set和get函数
foreach ($obj as $func_name => $value) {
if (!$value instanceOf Closure) {
$obj->{"set" . ucfirst($func_name)} = function($stdObject, $value) use ($func_name) { // Note: you can also use keyword 'use' to bind parent variables.
$stdObject->{$func_name} = $value;
};
$obj->{"get" . ucfirst($func_name)} = function($stdObject) use ($func_name) { // Note: you can also use keyword 'use' to bind parent variables.
return $stdObject->{$func_name};
};
}
}
//调用函数
$obj->setName("John"); //会首先调用__call函数,之后会回调到闭包函数定义的地方
$obj->setAdresse("Boston");
$obj->getInfo();
?>