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中的对象,类。与 方法的重载。
对象: 一切皆为对象.对象包括两部分内容:属性(名词形容词),行为(动词).对象和对象之间是有关系的: 派生,关联,依赖. 类: 对同一类别的众多对象的一种抽象.类,还是用来生成对象的一种模板,对象是 ...
随机推荐
- adb :unknown host service
adb 没法重启 现象:C:\Users\John>adb shell adb server is out of date. killing... ...
- jquery-qrcode在线生成二维码
通过bower进行获取: y@y:ydkt$ bower install jquery-qrcode --save bower not-cached git://github.com/gcusnieu ...
- uva 10032 Problem F: Tug of War
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&p ...
- Python模块如何安装 并确认模块已经安装好?
看自己有没有安装好,最简单的办法在可以再控制台下: C:\Users\sony>python Python 2.7.6 (default, Nov 10 2013, 19:24:18) [MSC ...
- Basefragment的封装使用
1.前言 封装作为面向对象的三大特性之一,在我们平时的coding过程用的那是非常的多的.大多数时候,我们可以根据封装情况评判代码的质量水平. 本文主要讲解的是fragment的封装.大体上,在项目的 ...
- mysql之事务
事务处理 begin 开始一个事物 commit 事务确认 rollback 事务回滚 end 事务结束 innodb下可以实现事务 开始执行事务时如果 ...
- codeforces 277.5 div2 F:组合计数类dp
题目大意: 求一个 n*n的 (0,1)矩阵,每行每列都只有两个1 的方案数 且该矩阵的前m行已知 分析: 这个题跟牡丹江区域赛的D题有些类似,都是有关矩阵的行列的覆盖问题 牡丹江D是求概率,这个题是 ...
- 关于apriori算法的一个简单的例子
apriori算法是关联规则挖掘中很基础也很经典的一个算法,我认为很多教程出现大堆的公式不是很适合一个初学者理解.因此,本文列举一个简单的例子来演示下apriori算法的整个步骤. 下面这个表格是代表 ...
- python unicodeDecode error
混淆了 python2 里边的 str 和 unicode 数据类型. 0. 你需要的是让编码用实际编码而不是 ascii 1. 对需要 str->unicode 的代码,可以在前边写上 imp ...
- js基础例子动态创建table实例
<style> table{ width:500px; font-weight: bold; border: 1px solid #000; border-collapse:collaps ...