PHP的重载-使用魔术方法实现
摘录PHP官网对PHP重载的解释:
PHP所提供的"重载"(overloading)是指动态地"创建"类属性和方法。我们是通过魔术方法(magic methods)来实现的。
当调用当前环境下未定义或不可见的类属性或方法时,重载方法会被调用。本节后面将使用"不可访问属性(inaccessible properties)"和"不可访问方法(inaccessible methods)"来称呼这些未定义或不可见的类属性或方法。
所有的重载方法都必须被声明为 public。
Note:
这些魔术方法的参数都不能通过引用传递。
Note:
PHP中的"重载"与其它绝大多数面向对象语言不同。传统的"重载"是用于提供多个同名的类方法,但各方法的参数类型和个数不同。
属性重载
public __set ( string $name , mixed $value ) : void
public __get ( string $name ) : mixed
public __isset ( string $name ) : bool
public __unset ( string $name ) : void
在给不可访问属性赋值时,__set() 会被调用。
读取不可访问属性的值时,__get() 会被调用。
当对不可访问属性调用 isset() 或 empty() 时,__isset() 会被调用。
当对不可访问属性调用 unset() 时,__unset() 会被调用。
参数 $name 是指要操作的变量名称。__set() 方法的 $value 参数指定了 $name 变量的值。
属性重载只能在对象中进行。在静态方法中,这些魔术方法将不会被调用。所以这些方法都不能被 声明为 static。
Note:
因为 PHP 处理赋值运算的方式,__set() 的返回值将被忽略。类似的, 在下面这样的链式赋值中,__get() 不会被调用:
$a = $obj->b = 8;
Note:
在除 isset() 外的其它语言结构中无法使用重载的属性,这意味着当对一个重载的属性使用 empty() 时,重载魔术方法将不会被调用。
为避开此限制,必须将重载属性赋值到本地变量再使用 empty()。
Example #1 使用 __get(),__set(),__isset() 和 __unset() 进行属性重载
class PropertyTest
{
/** 被重载的数据保存在此 */
private $data = array(); /** 重载不能被用在已经定义的属性 */
public $declared = 1; /** 只有从类外部访问这个属性时,重载才会发生 */
private $hidden = 2; public function __set ($name, $value)
{
$this->data[$name] = $value;
} public function __get ($name)
{
if (isset($this->$name)) {
return $this->$name;
}
if (array_key_exists($name, $this->data)) {
return $this->data[$name];
}
//产生一条回溯跟踪
$trace = debug_backtrace();
//抛出异常
trigger_error('Undefined property via __get(): ' . $name . ' in ' . $trace[0]['file'] . ' on line ' . $trace[0]['line'], E_USER_NOTICE);
return null;
} public function __isset ($name)
{
return isset($this->data[$name]);
} public function __unset ($name)
{
unset($this->data[$name]);
} /** 非魔术方法 */
public function getHidden ()
{
return $this->hidden;
}
} $obj = new PropertyTest; //输出不存在的a变量,走到__get()中,会抛出异常
echo $obj->a; //对不存在的a变量赋值为1,会走到__set()中
$obj->a = 1; //再次输出a变量,由于上面已经对其__set(),所以这是可以访问到a的值为1
echo $obj->a; //此时使用isset()对不存在的a变量进行运算时,会走到__isset()中,由于上面已经对其__set(),所以是true
var_dump(isset($obj->a)); //对a进行unset()时,会走到__unset()中
unset($obj->a); //再对其进行isset(),此时已经不存在了
var_dump(isset($obj->a)); //访问private 属性的变量,会进入__get()中
echo $obj->hidden;
方法重载
public __call ( string $name , array $arguments ) : mixed
public static __callStatic ( string $name , array $arguments ) : mixed
在对象中调用一个不可访问方法时,__call() 会被调用。
在静态上下文中调用一个不可访问方法时,__callStatic() 会被调用。
$name 参数是要调用的方法名称。
$arguments 参数是一个枚举数组,包含着要传递给方法 $name 的参数。
Example #2 使用 __call() 和 __callStatic() 对方法重载
class MethodTest
{
/**
* 调用不存在的方法时进入此处
* @param $name
* @param $arguments
*/
public function __call ($name, $arguments)
{
// 注意: $name 的值区分大小写
$info = [
'name' => $name,
'arguments' => $arguments,
];
print_r($info);
} /**
* PHP 5.3.0之后版本
* 调用不存在的静态方法时,进入此处
*/
public static function __callStatic ($name, $arguments)
{
// 注意: $name 的值区分大小写
$info = [
'name' => $name,
'arguments' => $arguments,
];
print_r($info);
}
} $arguments = ['A', 'B', 'C']; $obj = new MethodTest;
$obj->test(...$arguments); MethodTest::test(...$arguments); // PHP 5.3.0之后版本 /*
* 以上两个都输出:
* Array
(
[name] => test
[arguments] => Array
(
[0] => A
[1] => B
[2] => C
) )
*/
PHP的重载-使用魔术方法实现的更多相关文章
- PHP的重载及魔术方法
首先你要知道什么是php的魔术方法,它不是变魔术的,如果你想学习变魔术来错地方了哦! 定义:PHP 将所有以 __(两个下划线)开头的类方法保留为魔术方法.所以在定义类方法时,除了上述魔术方法,建议不 ...
- 巧妙的重载魔术方法__call()
工作半年了,感觉这半年学到的东西比大学四年学到的还要多,主要原因是心静下来了,目标也明确了,不会去整天的和游戏纠缠在一起了.大学时候其实也意识到了玩游戏会影响自己的正常学习和工作的,但是一直控制不了自 ...
- php魔术方法——属性重载方法
php有一类很神奇的方法,这些方法是保留方法,通常不会在外部被显式调用,他们使用双下划线(__)开头,他们被称为魔术方法(Magic Methods).php官方也不建议定义其他双下划线开头的方法. ...
- php用魔术方法__call实现类函数重载
因为php是弱类型语言,不喜欢c++通过改变函数返回相同的值键入的参数的数目和功能将过载!但在需求函数的实际发展可能过载.开发需求,我们能够通过魔术方法__call()来实现函数重载. class T ...
- php中的重载以及几个常用的魔术方法示例
在面向对象语言中,有一个很重要的概念——overload,即重载.所谓重载,一般是用于在一个类内实现若干重载的方法,这些方法的名称相同而参数形式不同.但是,在php中,这个概念跟大多面向对象语言中的“ ...
- Pthon魔术方法(Magic Methods)-运算符重载
Pthon魔术方法(Magic Methods)-运算符重载 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Python运算符对应的魔术方法 1>.比较运算符 <: ...
- php魔术方法使用场景
php魔术方法-----__tostring(),__invoke,__call(),__callStatic ... __tostring(),__invoke() __tostring()方法是在 ...
- PHP 类中的魔术方法
定义: PHP类中以两个下画线“__”开头的方法被称为魔术方法. 分类: 例如:构造方法:__construct:析构方法:__destruct:动态重载:__set().__get().__call ...
- php魔术方法罗列
##__sleep() 和 __wakeup() 当序列化(serialize)对象时,PHP 将试图在序列动作之前调用该对象的成员函数 __sleep() .__sleep() 方法常用于提交未提交 ...
随机推荐
- 【洛谷p1309】瑞士轮
因为太菜不会写P1310 表达式的值,就只能过来水两篇博客啦qwq 另外这个题我是开o2才过的(虽然是写了归并排序)(可能我太菜写的归并不是还可以“剪枝”吧qwq)哎,果真还是太菜啦qwq 所以准备写 ...
- Python pass是空语句用法
在条件判断,还是函数中,有时候不需要输出任何东西,也不能留空,python提供空的语句,下面讲述pass空语句的用法 1,关键词 pass 2,用法 for letter in 'Python': i ...
- jmeter性能测试遇到的问题
1.出现socket closed问题: 修改方式: 问题原因:在JMeter下,发送http 请求时,一般都是默认选择了use keepAlive(这个是什么?看后面资料),这个是连接协议,JMet ...
- Neo4j 修改关系类型 type
没有直接修改的函数,也不需要,下面代码就可以: MATCH (n:User {name:"foo"})-[r:REL]->(m:User {name:"bar&qu ...
- Angular.js 使用$http的response得到的phone属性为undefined
这是个坑~ 先说解决方案:把response打印出来找你的属性 记录一下,经验不足,有些东西想当然了,所有错误出现都应该一步步去排查!!!切记想当然的自以为. 源码: js $scope.phone= ...
- 一个完整的HTTP请求过程详细
整个流程1.域名解析 —> 2.与服务器建立连接 —> 3.发起HTTP请求 —>4. 服务器响应HTTP请求,浏览器得到html代码 —> 5.浏览器解析html代码,并请求 ...
- There is no Action mapped for namespace [/] and action name [TestAction] ass
1.修改action的name值 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE strut ...
- hdu4348 To the moon (可持久化线段树)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4348 题目大意:给定含有n个数的序列,有以下四种操作 1.C l r d:表示对区间[l,r]中的数加 ...
- C++11的新特性:右值引用
先看代码 #include "pch.h" #include <iostream> #include <string> using namespace st ...
- POJ 3889 Fractal Streets(逼近模拟)
$ POJ~3889~Fractal~Streets $(模拟) $ solution: $ 这是一道淳朴的模拟题,最近发现这种题目总是可以用逼近法,就再来练练手吧. 首先对于每个编号我们可以用逼近法 ...