前端学PHP之面向对象系列第二篇——魔术方法
前面的话
php在面向对象部分有很多相关的魔术方法,这些方法为面向对象实现提供了便利,本文将详细介绍魔术方法
构造方法
大多数类都有一种称为构造函数的特殊方法。当创建一个对象时,它将自动调用构造函数,通常用它执行一些有用的初始化任务
构造函数的声明与其它操作的声明一样,只是其名称必须是两个下划线__construct( )。这是PHP5中的变化;PHP4的版本中,构造函数的名称必须与类名相同。为了向下兼容,如果一个类中没有名为__construct( )的方法,PHP将搜索一个与类名相同的方法
void __construct ([ mixed $args [, $... ]] )
如果子类中定义了构造函数则不会隐式调用其父类的构造函数。要执行父类的构造函数,需要在子类的构造函数中调用 parent::__construct()。如果子类没有定义构造函数则会如同一个普通的类方法一样从父类继承(假如没有被定义为 private 的话)
<?php
class BaseClass {
function __construct() {
print "In BaseClass constructor\n";
}
}
class SubClass extends BaseClass {
function __construct() {
parent::__construct();
print "In SubClass constructor\n";
}
}
class OtherSubClass extends BaseClass {
}
// In BaseClass constructor
$obj = new BaseClass(); // In BaseClass constructor
// In SubClass constructor
$obj = new SubClass(); // In BaseClass constructor
$obj = new OtherSubClass();
?>
析构方法
与构造方法相对的就是析构方法。析构方法是PHP5新添加的内容,在PHP4中没有析构方法。析构方法是在对象被销毁之前自动调用的方法,主要执行一些特定的操作,例如关闭文件,释放结果集等
与构造方法类似,一个类的析构方法名称必须是两个下划线 __destruct( )。析构函数不能带有任何参数
<?php
class MyDestructableClass {
function __construct() {
print "In constructor\n";
$this->name = "MyDestructableClass";
}
function __destruct() {
print "Destroying " . $this->name . "\n";
}
}
//In constructor Destroying MyDestructableClass
$obj = new MyDestructableClass();
?>
不可访问属性
get()
读取不可访问属性(protected、private)时,__get()会被调用,并将属性名以第一个参数(string)传进此方法中
public mixed __get ( string $name )
<?php
class demo{
protected $protected = 1;
public $public = 2;
private $private = 3;
function __get($name){
echo "111{$name}111<br>";
}
}
$d1 = new demo;
$d1->protected;//111protected111
$d1->public;
$d1->private;//111private111
?>
set()
在给不可访问属性(protected、private)赋值时,__set() 会被调用,并将属性名以第一个参数(string),值作为第二参数(mixed)传进此方法中
public void __set ( string $name , mixed $value )
<?php
class demo{
protected $protected = 1;
public $public = 2;
private $private = 3;
function __set($name,$value){
echo "0{$name}0{$value}<br>";
}
}
$d1 = new demo;
$d1->protected = '1';//0protected01
$d1->public = '2';
$d1->private = '3';//0private03
?>
isset()
当对不可访问属性(protected、private)调用 isset() 或 empty() 时,__isset() 会被调用
public bool __isset ( string $name )
<?php
class demo{
protected $protected = 1;
public $public = 2;
private $private = 3;
function __isset($name){
echo "0{$name}0<br>";
}
}
$d1 = new demo;
empty($d1->protected);//0protected0
empty($d1->public);
empty($d1->private);//0private0
?>
unset()
当对不可访问属性(protected、private)调用unset()时,__unset()会被调用
public void __unset ( string $name )
<?php
class demo{
protected $protected = 1;
public $public = 2;
private $private = 3;
function __unset($name){
echo "0{$name}0<br>";
}
}
$d1 = new demo;
unset($d1->protected);//0protected0
unset($d1->public);
unset($d1->private);//0private0
?>
对象复制
clone()
在对象克隆时会自动调用clone()方法,这方法不需要任何参数,可以通过该方法对克隆后的副本重新初始化
clone()方法会自动包含this和that两个对象的引用,this是副本对象的引用,that是原本对象的引用
<?php
class Person{
private $name;
private $sex;
private $age;
function __construct($name="",$sex="",$age=1){
$this->name= $name;
$this->sex = $sex;
$this->age = $age;
}
function __clone(){
$this->name = $this->name."的副本";
}
function say(){
echo "我的名字:" .$this->name.",性别:".$this->sex.",年龄:".$this->age."<br>";
}
}
$p1 = new Person('张三','男','20');
$p2 = clone $p1;
$p1->say();//我的名字:张三,性别:男,年龄:20
$p2->say();//我的名字:张三的副本,性别:男,年龄:20
?>
字符串
toString()
__toString()方法用于一个类被当成字符串时应怎样回应,它是快速获取对象的字符串表示的最便捷的方式,是直接输出对象引用时自动调用的方法
<?php
class TestClass
{
public $foo;
public function __construct($foo)
{
$this->foo = $foo;
}
public function __toString() {
return $this->foo;
}
}
$class = new TestClass('Hello');
echo $class;//Hello
?>
对象不存在
call()
在对象中调用一个不可访问方法时,__call()会被调用
callStatic()
在静态上下文中调用一个不可访问方法时,__callStatic()会被调用
<?php
class MethodTest
{
public function __call($name, $arguments)
{
echo "Calling object method '$name' "
. implode(', ', $arguments). "\n";
}
public static function __callStatic($name, $arguments)
{
echo "Calling static method '$name' "
. implode(', ', $arguments). "\n";
}
}
$obj = new MethodTest;
//Calling object method 'runTest' in object context
$obj->runTest('in object context');
//Calling static method 'runTest' in static context
MethodTest::runTest('in static context');
?>
自动加载类
autoload()
在PHP5中,可以定义一个__autoload()函数,它会在试图使用尚未被定义的类时自动调用。通过调用此函数,脚本引擎在PHP出错失败前有了最后一个机会加载所需的类
<?php
function __autoload($class_name) {
require_once $class_name . '.php';
} $obj = new MyClass1();
$obj2 = new MyClass2();
?>
串行化
sleep()
在调用serialize()函数将对象串行化时,检查类中是否存在一个魔术方法 __sleep()。如果存在,该方法会先被调用,然后才执行序列化操作。此功能可以用于清理对象,并返回一个包含对象中所有应被序列化的变量名称的数组。如果该方法未返回任何内容,则 NULL 被序列化,并产生一个 E_NOTICE 级别的错误
__sleep()函数不需要接受任何参数,但需要返回一个数组,在数组中包含需要串行化的属性。未被包含在数组中的属性将在串行化时被忽略。如果没有在类中声明__sleep()方法,对象中的所有属性都将被串行化
wakeup()
在调用unserialize()函数将对象反串行化对象时,则会自动调用对象中的__wakeup()方法,用来在二进制串重新组成一个对象时,为新对象中的成员属性重新初始化
wakeup()经常用在反序列化操作中,例如重新建立数据库连接,或执行其它初始化操作
<?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();
}
}
?>
函数调用
invoke()
当尝试以调用函数的方式调用一个对象时,__invoke()方法会被自动调用
<?php
class CallableClass
{
function __invoke($x) {
var_dump($x);
}
}
$obj = new CallableClass;
$obj(5);//int(5)
var_dump(is_callable($obj));//bool(true)
?>
【补充】
set_state()
当调用var_export()导出类时,set_state()方法会被调用,本方法的唯一参数是一个数组,其中包含按 array('property' => value, ...) 格式排列的类属性
[注意]var_export()返回关于传递给该函数的变量的结构信息,它和var_dump()类似,不同的是其返回的表示是合法的PHP代码,也就是说,var_export返回的代码,可以直接当作php代码赋给一个变量。 而这个变量就会取得和被var_export一样的类型的值
<?php
class A
{
public $var1;
public $var2;
public static function __set_state($an_array)
{
$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) . ';');
/*
object(A)[2]
public 'var1' => int 5
public 'var2' => string 'foo' (length=3)
*/
var_dump($b);
?>
前端学PHP之面向对象系列第二篇——魔术方法的更多相关文章
- 前端学PHP之面向对象系列第一篇——类和对象
× 目录 [1]类 [2]成员属性[3]成员方法[4]对象[5]成员访问[6]this 前面的话 面向对象程序设计(OOP)是一种计算机编程架构.计算机程序由单个能够起到子程序作用的单元或对象组成,为 ...
- 前端学PHP之面向对象系列第六篇——简单图形面积计算器实现
前面的话 本文用面向对象的技术来实现一个简单的图形面积计算器 图形类 //rect.class.php <?php abstract class Shape{ public $name; abs ...
- 前端学PHP之面向对象系列第五篇——对象操作
× 目录 [1]对象克隆 [2]对象比较[3]对象串行化[4]json 前面的话 本文主要介绍面向对象中的一些对象操作 对象克隆 对象复制,又叫对象克隆,可以通过 clone 关键字来完成 在多数情况 ...
- 前端学PHP之面向对象系列第四篇——关键字
× 目录 [1]public [2]protected [3]private[4]final[5]static[6]const[7]this[8]self[9]parent 前面的话 php实现面向对 ...
- 前端学PHP之面向对象系列第三篇——三大特性
× 目录 [1]封装 [2]继承[3]多态 前面的话 php面向对象编程的三大特性是封装性.继承性和多态性.本文将介绍php的这三大特性 封装 封装就是把对象中的成员属性和成员方法加上访问修饰符( p ...
- 前端学PHP之面向对象系列第四篇-----关键字
public public表示公有,它具有最大的访问权限,被定义为公有的类成员可以在任何地方被访问 如果属性用 var 定义,则被视为公有,如果方法没有设置关键字,则该方法默认为公有 <?php ...
- javascript面向对象系列第二篇——创建对象的5种模式
× 目录 [1]字面量 [2]工厂模式 [3]构造函数[4]原型模式[5]组合模式 前面的话 如何创建对象,或者说如何更优雅的创建对象,一直是一个津津乐道的话题.本文将从最简单的创建对象的方式入手,逐 ...
- 前端工程师技能之photoshop巧用系列第二篇——测量篇
× 目录 [1]测量信息 [2]实战 [3]注意事项 前面的话 前端工程师使用photoshop进行的大量工作实际上是测量.本文是photoshop巧用系列第二篇——测量篇 测量信息 在网页制作中需要 ...
- 深入理解javascript函数系列第二篇——函数参数
× 目录 [1]arguments [2]内部属性 [3]函数重载[4]参数传递 前面的话 javascript函数的参数与大多数其他语言的函数的参数有所不同.函数不介意传递进来多少个参数,也不在乎传 ...
随机推荐
- 2632: [neerc2011]Gcd guessing game
2632: [neerc2011]Gcd guessing game Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 144 Solved: 84[S ...
- MVC高级编程+C#高级编程
本人今年的目标是学习MVC高级编程和C#高级编程,把自己的基础打的扎实,本文中值是一个开到,定期会在上面记录学习的技术点和心得就,加油吧!!!!!
- 软件工程:Wordcount程序作业
由于时间的关系,急着交作业,加上这一次也不是那么很认真的去做,草草写了“Wordcount程序”几个功能,即是 .txt文件的读取,能计算出文件内容的单词数,文件内容的字符数,及行数. 这次选用C来做 ...
- web-inf目录和meta-inf目录
/WEB-INF/web.xml Web应用程序配置文件,描述了 servlet 和其他的应用组件配置及命名规则. /WEB-INF/classes/ 包含了站点所有用的 class 文件,包括 se ...
- myEclipse Could not create the view: An unexpected exception was thrown.
myEclipse 非正常关闭,打开后 service Explorer or Package Explorer 视图显示不出来.报“Could not create the view: An une ...
- 【Telerik】<telerik:RadComboBox>导出列表数据
近来在做项目,做到导出功能.使用<telerik:RadComboBox>的下拉框来实现导出部分或导出所有数据的功能.
- 李洪强iOS经典面试题154- 通知与推送
李洪强iOS经典面试题154- 通知与推送 通知与推送 本地通知和远程推送通知对基本概念和用法? image 本地通知和远程推送通知都可以向不在前台运行的应用发送消息,这种消息既可能是即将发生的事 ...
- [IOS]swift 使用AVOS的API
避免写后台代码,但保证app能够有后台,使用了AVOS这个产品来帮助自己的app联网,AVOS是很强大的云服务,基本原理和Parse差不多,只是parse在国外可能对国内用户联网速度上有点限制. 下面 ...
- tableView:cellForRowAtIndexPath:方法中indexPath.row不是从0开始的,从4开始
问题描述:重新刷新数据源,刷新列表时,发现前面4个cell没有显示出来,直接从第5条开始的,这是什么东东? 在tableView:numberOfRowsInSection:方法里打印数据源个数,是正 ...
- tomcat:域名指向项目名
把项目部署到tomcat目录webapps后,使用域名访问的时候域名后面需要加上项目名称,如果想直接输入域名就可以访问项目呢?看了下tomcat官方文档,我修改了tomcat安装目录下conf/ser ...