PHP的重载及魔术方法
首先你要知道什么是php的魔术方法,它不是变魔术的,如果你想学习变魔术来错地方了哦!
定义:PHP 将所有以 __(两个下划线)开头的类方法保留为魔术方法。所以在定义类方法时,除了上述魔术方法,建议不要以 __ 为前缀。
作用:利用模式方法可以轻松实现PHP面向对象中重载(Overloading即动态创建类属性和方法)
其实很多博客主已经写过这些方法了、、、但是我还是要说一遍。。谁让你来听了呢,码这么多字也不容易看完再走吧!
1.__construct,__destruct
__constuct构建对象的时被调用;
__destruct明确销毁对象或脚本结束时被调用;
- class Foo {
- private $name;
- private $link;
- public function __construct($name) {
- $this->name = $name;
- }
- public function __destruct() {
- echo 'Destroying: ', $this->name, PHP_EOL;//PHP_EOL代表php的换行符
- }
- }
打住,先安利一波重载的定义及使用方法:
定义:PHP所提供的"重载"(overloading)是指动态地"创建"类属性和方法。(我们是通过魔术方法(magic methods)来实现的)
作用:当调用当前环境下未定义或不可见的类属性或方法时,重载方法会被调用。后面将使用"不可访问属性(inaccessible properties)"和"不可访问方法(inaccessible methods)"来称呼这些未定义或不可见的类属性或方法。
注意:所有的重载方法都必须被声明为 public。
2.__get、__set、__isset、__unset、__call、__callStatic //为啥放一起呢?
__set当给不可访问或不存在属性赋值时被调用
__get读取不可访问或不存在属性时被调用
__isset对不可访问或不存在的属性调用isset()或empty()时被调用
__unset对不可访问或不存在的属性进行unset时被调用
__call调用不可访问或不存在的方法时被调用
__callStatic调用不可访问或不存在的静态方法时被调用
Example #1 使用 __get(),__set(),__isset() 和 __unset() 进行属性重载
- <?php
- class PropertyTest {
- /** 被重载的数据保存在此 */
- private $data = array();
- /** 重载不能被用在已经定义的属性 */
- public $declared = 1;
- /** 只有从类外部访问这个属性时,重载才会发生 */
- private $hidden = 2;
- public function __set($name, $value)
- {
- echo "Setting '$name' to '$value'\n";
- $this->data[$name] = $value;
- }
- public function __get($name)
- {
- echo "Getting '$name'\n";
- 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;
- }
- /** PHP 5.1.0之后版本 */
- public function __isset($name)
- {
- echo "Is '$name' set?\n";
- return isset($this->data[$name]);
- }
- /** PHP 5.1.0之后版本 */
- public function __unset($name)
- {
- echo "Unsetting '$name'\n";
- unset($this->data[$name]);
- }
- /** 非魔术方法 */
- public function getHidden()
- {
- return $this->hidden;
- }
- }
- echo "<pre>\n";
- $obj = new PropertyTest;
- $obj->a = 1;
- echo $obj->a . "\n\n";
- var_dump(isset($obj->a));
- unset($obj->a);
- var_dump(isset($obj->a));
- echo "\n";
- echo $obj->declared . "\n\n";
- echo "Let's experiment with the private property named 'hidden':\n";
- echo "Privates are visible inside the class, so __get() not used...\n";
- echo $obj->getHidden() . "\n";
- echo "Privates not visible outside of class, so __get() is used...\n";
- echo $obj->hidden . "\n";
- ?>
看完了吗?好好看!
5.__sleep,__wakeup
__sleep当使用serialize时被调用,当你不需要保存大对象的所有数据时很有用
__wakeup当使用unserialize时被调用,可用于做些对象的初始化操作
- <?php
- class Connection
- {
- protected $link;
- private $server, $username, $password, $db;
- public function __construct($server, $username, $password, $db)
- {
- $this->server = $server;
- $this->username = $username;
- $this->password = $password;
- $this->db = $db;
- $this->connect();
- }
- private function connect()
- {
- $this->link = mysql_connect($this->server, $this->username, $this->password);
- mysql_select_db($this->db, $this->link);
- }
- public function __sleep()
- {
- return array('server', 'username', 'password', 'db');
- }
- public function __wakeup()
- {
- $this->connect();
- }
- }
- ?>
6.__clone
进行对象clone时被调用,用来调整对象的克隆行为
- <?php
- class SubObject
- {
- static $instances = 0;
- public $instance;
- public function __construct() {
- $this->instance = ++self::$instances;
- }
- public function __clone() {
- $this->instance = ++self::$instances;
- }
- }
- class MyCloneable
- {
- public $object1;
- public $object2;
- function __clone()
- {
- // 强制复制一份this->object, 否则仍然指向同一个对象
- $this->object1 = clone $this->object1;
- }
- }
- $obj = new MyCloneable();
- $obj->object1 = new SubObject();
- $obj->object2 = new SubObject();
- $obj2 = clone $obj;
- print("Original Object:\n");
- print_r($obj);
- print("Cloned Object:\n");
- print_r($obj2);
- ?>
7.__toString
当一个类被转换成字符串时被调用
- <?php
- class SubObject
- {
- static $instances = 0;
- public $instance;
- public function __construct() {
- $this->instance = ++self::$instances;
- }
- public function __clone() {
- $this->instance = ++self::$instances;
- }
- }
- class MyCloneable
- {
- public $object1;
- public $object2;
- function __clone()
- {
- // 强制复制一份this->object, 否则仍然指向同一个对象
- $this->object1 = clone $this->object1;
- }
- }
- $obj = new MyCloneable();
- $obj->object1 = new SubObject();
- $obj->object2 = new SubObject();
- $obj2 = clone $obj;
- print("Original Object:\n");
- print_r($obj);
- print("Cloned Object:\n");
- print_r($obj2);
- ?>
8.__set_state
当调用var_export()导出类时,此静态方法被调用。用__set_state的返回值做为var_export的返回值。
- <?php
- class A
- {
- public $var1;
- public $var2;
- public static function __set_state($an_array) // As of PHP 5.1.0
- {
- $obj = new A;
- $obj->var1 = $an_array['var1'];
- $obj->var2 = $an_array['var2'];
- return $obj;
- }
- }
- $a = new A;
- $a->var1 = 5;
- $a->var2 = 'foo';
- eval('$b = ' . var_export($a, true) . ';'); // $b = A::__set_state(array(
- // 'var1' => 5,
- // 'var2' => 'foo',
- // ));
- var_dump($b);
- ?>
enmmm,我知道你记不住的。。这么多谁记得住啊,好烦啊、、、别,这还没讲完呢,更多方法请参考PHP的官方文档:http://php.net/manual/zh/,别打我,你自己去看吧,毕竟好东西还是要众乐乐的!了;另外这些代码你最好再编译器中运行一边,不然看完你估计和没看一个样2333 ····
作者原创、转载请注明出处
PHP的重载及魔术方法的更多相关文章
- PHP的重载-使用魔术方法实现
摘录PHP官网对PHP重载的解释: PHP所提供的"重载"(overloading)是指动态地"创建"类属性和方法.我们是通过魔术方法(magic method ...
- 巧妙的重载魔术方法__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() 方法常用于提交未提交 ...
随机推荐
- XML解析【介绍、DOM、SAX详细说明、jaxp、dom4j、XPATH】
什么是XML解析 前面XML章节已经说了,XML被设计为"什么都不做",XML只用于组织.存储数据,除此之外的数据生成.读取.传送等等的操作都与XML本身无关! XML解析就是读取 ...
- java实现excel和数据的交互
1. 环境要求 本文环境为: 数据库为oracle,jdk为jdk7,依赖jar包为ojdbc6-11.2.0.4.0.jar+poi-3.14.jar 2.POI 使用 1. 建立工作空间 2. 获 ...
- appium python andiroid自动化文档整理笔记
from appium import webdriver import time,unittest,HTMLTestRunner class Testlogin(unittest.TestCase): ...
- javascript DOM事件总结
1 <html> 2 <title>事件</title> 3 <meta charset="utf-8"/> 4 <body& ...
- cglib代理
简介: github地址:https://github.com/cglib/cglib,可以访问这个地址查看cglib源码和相关文档. 简单的摘录了wiki上关于cglib的描述: cglib is ...
- 多线程简单实例(1)真的需要synchronized么?
说道多线程的安全问题,很多人想到就就是加锁.用到synchronized关键字. 那就要先说说synchronized问什么能够保证线程安全了. 首先要了解线程的工作方式:线程工作分为工作内存和主内存 ...
- Pycharm中如何加载多个项目?
今天在使用Pycharm工具练习Python时遇到一个疑问:在已存有项目A工程的前提下如何新建另一个项目B,且两者并存? 基本操作步骤: 在File下拉项中选择"New Project&qu ...
- [js高手之路] html5 canvas系列教程 - 线形渐变,径向渐变与阴影设置
接着上文[js高手之路] html5 canvas系列教程 - 像素操作(反色,黑白,亮度,复古,蒙版,透明)继续. 一.线形渐变 线形渐变指的是一条直线上发生的渐变. 用法: var linear ...
- 【转】Keberos认证原理
前几天在给人解释Windows是如何通过Kerberos进行Authentication的时候,讲了半天也别把那位老兄讲明白,还差点把自己给绕进去.后来想想原因有以下两点:对于一个没有完全不了解Ker ...
- Linux脚本入门(1)
1. Linux 脚本编写基础1.1 语法基本介绍1.1.1 开头程序必须以下面的行开始(必须方在文件的第一行): #!/bin/sh 符号#!用来告诉系统它后面的参数是用来执行该文件的程序.在这个例 ...