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() 方法常用于提交未提交 ...
随机推荐
- IDEA开发环境设置
IDEA开发环境设置 1.关闭自动更新 IntelliJ IDEA默认会自动进行版本的更新,在网络异常时经常会导致各种各样的问题,因此强烈建议关闭自动更新. File->Settings 2.隐 ...
- mysql使用触发器生成唯一订单号,
需求:订单号唯一,并且期望是时间格式加其他字符串, 实现:采用触发机制,在新增时根据新增id值加1作为订单生成的随机且确定唯一的数,因为id唯一: 遇到问题:新增时不能提前知道id值, 解决:取到当前 ...
- accept()出的socket不会使用新的端口号
1 标识一个socket的是四元组,不只是端口号 client ip : client port : server ip : server port 2 accept出的新的socket仍然使用和li ...
- Nginx环境下设置zblog伪静态方法
Apache的环境非常简单.可以点击创建 .htaccess就可以了 Nginx环境下设置伪静态,并没有那个一键创建的按钮.只看到了这样的一个提示. 别的环境未测试.宝塔面板中 反正我是没找到. 宝塔 ...
- PL/SQL Developer工具
安装好Oracle以后我们发现在控制台来操作数据库很繁琐,而且也不方便阅读.所以,我们就要用到PL/SQL Developer工具,以达到能更好的操作数据库的目的. PL/SQL Developer简 ...
- [Codeforces 1197E]Culture Code(线段树优化建图+DAG上最短路)
[Codeforces 1197E]Culture Code(线段树优化建图+DAG上最短路) 题面 有n个空心物品,每个物品有外部体积\(out_i\)和内部体积\(in_i\),如果\(in_i& ...
- Lpl and Energy-saving Lamps
During tea-drinking, princess, amongst other things, asked why has such a good-natured and cute Drag ...
- SQLServer中ISNULL和CONVERT函数
create view sss as(select ISNULL(operate_time, CONVERT(VARCHAR(20),create_time,120)) time from s_pro ...
- C# 实现实体类和Xml转换
一.实体类转换成XML 将实体类转换成XML需要使用XmlSerializer类的Serialize方法,将实体类序列化 public static string XmlSerialize<T& ...
- linux查看 inotify 提供的工具
[root@rsync-client-inotify ~]# ll /usr/local/bin/inotify* -rwxr-xr-x. 1 root root 38582 Jun 3 22:23 ...