php魔术方法——属性重载方法
php有一类很神奇的方法,这些方法是保留方法,通常不会在外部被显式调用,他们使用双下划线(__)开头,他们被称为魔术方法(Magic Methods)。php官方也不建议定义其他双下划线开头的方法。
这次介绍属性重载方法:get/set/isset/unset
public void __set ( string $name , mixed $value ) public mixed __get ( string $name ) public bool __isset ( string $name ) public void __unset ( string $name )
这些方法触发的时机,都是在访问不可访问的属性的时候。
如以下:
<?php
class Cls{
private $a = 0;
protected $b = 1;
public $c = 2;
var $d = 3;
private $_properties = array(0);
public function __set($name, $value){
echo __METHOD__ . ' is called! ' . json_encode(func_get_args()) . "\n";
return $this->_properties[$name] = $value;
}
public function __get($name){
echo __METHOD__ . ' is called! ' . json_encode(func_get_args()) . "\n";
return $this->_properties[$name];
}
public function __isset($name){
echo __METHOD__ . ' is called! ' . json_encode(func_get_args()) . "\n";
return isset($this->_properties[$name]);
}
public function __unset($name){
echo __METHOD__ . ' is called! ' . json_encode(func_get_args()) . "\n";
unset($this->_properties[$name]);
}
public function dump(){
echo "====================== DUMP START ====================\n";
echo <<<STR
a: $this->a
b: $this->b
c: $this->c
d: $this->d\n
STR;
foreach($this->_properties as $k => $v){
echo <<<STR
Property $k: $v\n
STR;
}
echo "====================== DUMP STOP =====================\n";
}
}
$string = 'abcdef';
$obj = new Cls();
$list = array('isset', 'get', 'set', 'isset', 'unset', 'isset');
$obj->dump();
foreach($list as $method){
for($i = 0 ; $i < strlen($string) ; $i ++){
$char = $string{$i};
echo "------ $method : $char ------\n";
switch($method){
case 'isset':
echo json_encode($tmp = isset($obj->$char)) . "\n";
break;
case 'get':
echo json_encode($tmp = $obj->$char) . "\n";
break;
case 'set':
echo json_encode($tmp = $obj->$char = $char . "-val") . "\n";
break;
case 'unset':
unset($obj->$char);
break;
default:
break;
}
}
$obj->dump();
}
结果输出:
====================== DUMP START ====================
a: 0
b: 1
c: 2
d: 3
Property 0: 0
====================== DUMP STOP =====================
------ isset : a ------
Cls::__isset is called! ["a"]
false
------ isset : b ------
Cls::__isset is called! ["b"]
false
------ isset : c ------
true
------ isset : d ------
true
------ isset : e ------
Cls::__isset is called! ["e"]
false
------ isset : f ------
Cls::__isset is called! ["f"]
false
====================== DUMP START ====================
a: 0
b: 1
c: 2
d: 3
Property 0: 0
====================== DUMP STOP =====================
------ get : a ------
Cls::__get is called! ["a"]
null
------ get : b ------
Cls::__get is called! ["b"]
null
------ get : c ------
2
------ get : d ------
3
------ get : e ------
Cls::__get is called! ["e"]
null
------ get : f ------
Cls::__get is called! ["f"]
null
====================== DUMP START ====================
a: 0
b: 1
c: 2
d: 3
Property 0: 0
====================== DUMP STOP =====================
------ set : a ------
Cls::__set is called! ["a","a-val"]
"a-val"
------ set : b ------
Cls::__set is called! ["b","b-val"]
"b-val"
------ set : c ------
"c-val"
------ set : d ------
"d-val"
------ set : e ------
Cls::__set is called! ["e","e-val"]
"e-val"
------ set : f ------
Cls::__set is called! ["f","f-val"]
"f-val"
====================== DUMP START ====================
a: 0
b: 1
c: c-val
d: d-val
Property 0: 0
Property a: a-val
Property b: b-val
Property e: e-val
Property f: f-val
====================== DUMP STOP =====================
------ isset : a ------
Cls::__isset is called! ["a"]
true
------ isset : b ------
Cls::__isset is called! ["b"]
true
------ isset : c ------
true
------ isset : d ------
true
------ isset : e ------
Cls::__isset is called! ["e"]
true
------ isset : f ------
Cls::__isset is called! ["f"]
true
====================== DUMP START ====================
a: 0
b: 1
c: c-val
d: d-val
Property 0: 0
Property a: a-val
Property b: b-val
Property e: e-val
Property f: f-val
====================== DUMP STOP =====================
------ unset : a ------
Cls::__unset is called! ["a"]
------ unset : b ------
Cls::__unset is called! ["b"]
------ unset : c ------
------ unset : d ------
------ unset : e ------
Cls::__unset is called! ["e"]
------ unset : f ------
Cls::__unset is called! ["f"]
====================== DUMP START ====================
Cls::__get is called! ["c"]
Cls::__get is called! ["d"]
a: 0
b: 1
c:
d:
Property 0: 0
====================== DUMP STOP =====================
------ isset : a ------
Cls::__isset is called! ["a"]
false
------ isset : b ------
Cls::__isset is called! ["b"]
false
------ isset : c ------
Cls::__isset is called! ["c"]
false
------ isset : d ------
Cls::__isset is called! ["d"]
false
------ isset : e ------
Cls::__isset is called! ["e"]
false
------ isset : f ------
Cls::__isset is called! ["f"]
false
====================== DUMP START ====================
Cls::__get is called! ["c"]
Cls::__get is called! ["d"]
a: 0
b: 1
c:
d:
Property 0: 0
====================== DUMP STOP =====================
特别强调,当这个属性不存在(基于当前访问权限)的时候,才会触发这些方法。因此严重建议使用确定的键值进行get/set处理,特别是对应的键值不要有访问权限问题,如上例中的a和b,会导致在类内部、类外部、子类内处理的方式不同,开发时产生不可预知的返回值,极易产生bug。
empty方法不能调用属性重载方法。
$tmp = $obj->$char = $char . "-val"
此例中,__set自身的返回值将被忽略,同样__get也不会被调用。
此外:属性重载方法必须声明为public,同时参数不能使用引用传递,静态属性不能通过这些方法重载,这些方法也不能被声明为static。
当然,使用魔术方法的时候,也会对反射系统造成影响。
php魔术方法——属性重载方法的更多相关文章
- Python中类的方法属性与方法属性的动态绑定
最近在学习python,纯粹是自己的兴趣爱好,然而并没有系统地看python编程书籍,觉得上面描述过于繁琐,在网站找了一些学习的网站,发现廖雪峰老师的网站上面的学习资源很不错,而且言简意赅,提取了一些 ...
- JAVA笔记2__类/封闭性/构造方法/方法的重载/匿名对象
public class Main { public static void main(String[] args) { Chicken c1 = new Chicken(); Chicken c2 ...
- Java中方法的重载和重置(覆盖)的区别
简单来说,重载就是在同一类中允许同时存在一个以上的同名方法,只要这些方法的参数个数或类型不同即可,而重置(覆盖)是子类重新定义父类中己经定义的方法,即子类重写父类方法. 方法的重载 方法的重载就是在同 ...
- python中类中属性和方法的具体定义方法和使用
1. Python中类中特性分成属性和方法 属性和方法都分为私有和公有的,私有的只可以在本类中使用外部是无法访问的 2. 定义属性(成员变量)的语法格式(公有属性/私有属性) class 类名: de ...
- Java学习笔记17---成员方法的重载与重写
重载是指,一个类中定义了一个成员方法后,通过修改参数个数.参数类型或参数顺序,重新实现该方法,则这两个方法互为对方的重载方法. 重写是指,子类重新实现父类的成员方法. 重载后的方法,与原方法相比: ( ...
- Day1 方法的重载
方法的重载 方法的标识符包括: 1.方法名称 2.方法的参数(参数类型和参数的数量) 方法的重载:方法名称相同 但是方法参数不同(1.参数类型不同 2.参数类型相同 但是参数个数不同 3.类型和个 ...
- php之属性重载和方法重载
<?php /** * * @authors Your Name (you@example.org) * @date 2016-06-13 20:40:19 * @version $Id$ */ ...
- 速战速决 (5) - PHP: 动态地创建属性和方法, 对象的复制, 对象的比较, 加载指定的文件, 自动加载类文件, 命名空间
[源码下载] 速战速决 (5) - PHP: 动态地创建属性和方法, 对象的复制, 对象的比较, 加载指定的文件, 自动加载类文件, 命名空间 作者:webabcd 介绍速战速决 之 PHP 动态地创 ...
- java中的对象,类。与 方法的重载。
对象: 一切皆为对象.对象包括两部分内容:属性(名词形容词),行为(动词).对象和对象之间是有关系的: 派生,关联,依赖. 类: 对同一类别的众多对象的一种抽象.类,还是用来生成对象的一种模板,对象是 ...
随机推荐
- VS2012和2010 设置framework版本
记录下找着麻烦http://zhidao.baidu.com/question/537279472.html VS2010和VS2012或者sv2008和VS2010,高版本VS编译都会出现,使用VS ...
- DOM 之通俗易懂讲解
DOM是所有前端开发每天打交道的东西,但是随着jQuery等库的出现,大大简化了DOM操作,导致大家慢慢的“遗忘”了它的本来面貌.不过,要想深入学习前端知识,对DOM的了解是不可或缺的,所以本文力图系 ...
- 转:MFC 的程序中GetAt()的理解
BYTE 是 1字节长度 的 整型, int 是 4 字节长度 的 整型. CString::GetAt(0); 就是把 一个 CString 对象里 的字符串 中的第一个字符,把它的ASCII 值 ...
- javascript 要注意的事项
记入一些容易出错的地方 function someClass() { this.name = null; 或 undefined } var obj = new someClass(); consol ...
- 天底下最简单的QT画图板,就一个类,60行代码
简单直观.但是我有个问题是,这实际上不是在绘制直线,而是几千几万个超级短的“直线”,这样会不会效率很低呢? 注意,每次绘制的时候,需要一支笔,这支笔需要设置颜色和宽度(就像我们平时写字也要稍微挑一下笔 ...
- VS快捷键大全(转)
相信.Net开发人员都想能够熟记各种VS快捷键以提高平时开发的效率,但苦于记忆能力太差而快捷键又特别多,特别烦,所以作罢! 下面我将简单介绍一下我记忆VS快捷键的一些方法,希望对大家有所帮助. 1.窗 ...
- AES的S-BOX构造
利用GF(2^8)乘法逆元,以及矩阵运算,可以构造出AES的SBOX. 求乘法逆元的一般方法是利用扩展欧几里得定理,在这里我取了个巧. 因为我已经有了GF的指数表(见上一篇文),利用指数表可以轻易地构 ...
- Myeclipse自动生成javabean的get和set方法
用Myeclipse开发java web程序,写javabean的时候,如果字段很多的话,写get和set方法是一件很无语和浪费时间的事情,所以Myeclipse提供了一个自动生成这些方法的功能. 首 ...
- windows下配置caffe(环境:win7+vs2013+opencv3.0)
说明:大部分转载于initialneil的大作Caffe + vs2013 + OpenCV in Windows Tutorial (I) – Setup 准备工作: 1.下载CUDA7.5: ht ...
- [ES6] Promise
How to use: export default function getReplies(topicId){ return new Promise(function( resolve, rejec ...