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() 方法常用于提交未提交 ...
随机推荐
- 应用安全_WTS-WAF绕过
Access 检测: ?id=+AND+= ?id=+AND+=2 绕过: sqlmap.py -u http://www.xx.com/project.asp?id=29 --tables --ta ...
- Maven-maven安装、Eclipse配置maven
1.下载maven安装包,下载完成,解压到安装路径. 2.配置环境变量 3.修改setting.xml配置本地库,阿里云中央仓库 路径:C:\fyliu\software\apache-maven-3 ...
- Ant-编译构建(2)-第3方jar包引入、log4j2
1.项目目录结构图,lib包引入了一些关于common logging+log4j2相关的jar. 2.编写相关的build.xml <?xml version="1.0" ...
- 七层模型? IP ,TCP/UDP ,HTTP ,RTSP ,FTP 分别在哪层?
IP: 网络层TCP/UDP: 传输层HTTP.RTSP.FTP: 应用层协议
- 06-File-文件
文件 长久保存信息的一种数据信息集合 常用操作 打开关闭(文件一旦打开,需要关闭操作) 读写内容 查找 open函数 open函数负责打开文件,带有很多参数 第一个参数: 必须有,文件的路径和名称 m ...
- WPF绑定各种数据源之xml数据源
一.WPF绑定各种数据源索引 WPF 绑定各种数据源之Datatable WPF绑定各种数据源之object数据源 WPF绑定各种数据源之xml数据源 WPF绑定各种数据源之元素控件属性 Bindin ...
- ][mybatis]MyBatis mapper文件中的变量引用方式#{}与${}的差别
转自https://blog.csdn.net/szwangdf/article/details/26714603 MyBatis mapper文件中的变量引用方式#{}与${}的差别 默认情况下,使 ...
- CentOS7搭建Flume与Kafka整合及基础操作与测试
前提 已完成Kafka的搭建,具体步骤参照CentOS7搭建Kafka单机环境及基础操作 Flume安装 下载 wget http://mirrors.tuna.tsinghua.edu.cn/apa ...
- Redis的客户端Jedis
1. Redis支持消息的订阅与发布 Redis的消息订阅支持:先订阅后发布 订阅:subscribe c1 c2 发布:publish c2 hello-redis 支持通配符的订阅:psubscr ...
- Java基础学习(3)
Java基础学习(三) Java异常 Throwable类:所有异常的祖先类 Error:虚拟机异常.内存错误.没法处理 Exception:编码.环境.用户操作输入出现问题 非检查异常(自动捕获): ...