PHP面向对象 – 魔术方法 __clone __tostring __call __autoload

__clone 魔术方法 -- 深度克隆对象

有时可能需要根据一个对象完全克隆出一个一模一样的对象,而且克隆以后,两个对象互不干扰。

格式:

$obj = new Class();

$objcopy = clone $obj;

魔术方法: __clone()

当执行 clone 克隆时会自动调用的方法,主要用于解决对象中特殊属性的复制操作。

 

用“=”赋值实例,实际上时引用赋值,改变其中一个的值,另一个实例也会被改变。如下面的栗子

class person{
	public $name;
}
$m1 = new person();
$m1->name = 'zhangsan';
$m2 = $m1;
$m2->name = 'lisi';
echo $m1->name.'<br>';	//输出结果 lisi ,在给m2设置值时$m1的值也被改变

因为 $m1 和 $m2 都是指向同一个内存区的引用,所以修改一个对象,另外一个也会同时会被修改。

为了让复制的对象跟之前对象没有任何关系,我们要用到PHP的clone操作:

1.浅克隆

使用PHP的clone操作复制对象,可以实现克隆。如下面栗子:

class person1{
	public $name;	
}
$m3 = new person1();
$m3->name = 'zhangsan';
$m4 = clone $m3;
$m4->name = 'lisi';
echo $m3->name.'<br>';	//输出结果 zhangsan
echo $m4->name.'<br>';	//输出结果 lisi

以上是浅克隆,只能做基本的克隆操作,如果对象的成员属性本身就是refence类型(引用),clone之后这些成员并没有被真正复制,如下面的栗子:

class person2{
	public $name;
}
$a = 'zhangsan';
$m5 = new person2();
$m5->name = &$a;
$m6 = clone $m5;
$m6->name = 'lisi';
echo $m5->name.'<br>';	//输出结果 lisi

class stu{
	public $grade;
	public $student;
	public function __construct(){
		$this->student = new person2();
	}
}
$m7 = new stu();
$m7->student->name = 'xiaoming';
$m8 = clone $m7;
$m8->student->name = 'lili';
echo $m7->student->name.'<br>';	//输出 lili

2.深克隆

在类中使用魔术方法 __clone 实现对象的深度克隆。

class person3{
	public $name;
}
class stu{
	public $grade;
	public $student;
	public function __construct(){
		$this->student = new person2();
	}
	public function __clone(){
		$this->student = clone $this->student;
	}
}
$m7 = new stu();
$m7->student->name = 'xiaoming';
$m8 = clone $m7;
$m8->student->name = 'lili';
echo $m7->student->name.'<br>';	//输出 xiaoming

__tostring() 魔术方法 -- 直接输出一个对象时自动调用

魔术方法“__toString()”是快速获取对象的字符串表示的最快捷方式。即当我们直接要输出一个对象时,如echo $a,print $a,那么会自动调用的此魔术方法。

注意: __toString()方法必须返回一个字符串类型的值。

class person{
	public $name;
	public $age;
	public function __construct($name,$age){
		$this->name = $name;
		$this->age = $age;
	}
	public function __tostring(){
		echo 'I am '.$this->name.', now '.$this->age.' years.<br>';
	}
}
$p = new person('lisi',15);
echo $p;	//输出结果 I am lisi, now 15 years.

__call() 魔术方法 -- 访问不存在的方法时自动调用

当试图调用一个对象中不存在的方法时,就会产生错误。PHP提供了__call() 这个方法来处理这种情况。即当调用一个不可访问方法(如未定义,或者不可见)时,__call() 会被调用。

格式: mixed __call(string $name, array $arguments)

说明: 第一个参数:$name表示方法名  第二个参数:$arguments表示调用时的参数列表(数组格式)

class person{
	public function __call($name,$ags){
		echo 'Function '.$name.' not exsit<br>';
		var_dump($ags);
	}
}
$p = new person();
$p->test('lisi',20);	//输出 Function test not exsit array(2) { [0]=> string(4) "lisi" [1]=> int(20) }

__autoload()魔术方法 -- new 实例化一个不存在的类时自动调用

PHP5 中当 new 实例化一个不存在的类时,则自动调用此函数__autoload(),并将类名作为参数传入此函数。可以使用这个实现类的自动加载。

PHP在魔术函数__autoload()方法出现以前,如果你要在一个程序文件中实例化100个对象,那么你必须用include或者require包含进来100个类文件,或者你把这100个类定义在同一个类文件中——相信这个文件一定会非常大。

但是__autoload()方法出来了,以后就不必为此大伤脑筋了,这个类会在你实例化对象之前自动加载制定的文件。

下边我们通过一个例子来看一下,具体的使用方法,并在稍后说明使用PHP魔术函数__autoload应该注意些什么。

function __autoload($classname){
	$classpath = './'.$classname.'.php';
	if(file_exists($classpath)){
		require_once($classpath);
	}else{
		echo 'class file '.$calsspath.' not found!';
	}
}
class classB extends classA{
	public function say(){
		echo 'I am '.$this->name;
	}
}

$c = new classB('lisi');
echo $c->say();	//输出 I am lisi

这个文件的运行是一点问题都没有的,可见autoload是多么的好用啊,呵呵……
但是不得不提醒你一下几个方面是必须要注意的。

1、如果类存在继承关系(例如:ClassB extends ClassA),并且ClassA不在ClassB所在目录
利用__autoload魔术函数实例化ClassB的时候就会受到一个致命错误:
代码如下 复制代码
Fatal error: Class ‘Classd’ not found in ……ClassB.php on line 2,

解决方法:把所有存在extends关系的类放在同一个文件目录下,或者在实例化一个继承类的时候在文件中手工包含被继承的类;

2、另外一个需要注意的是,类名和类的文件名必须一致,才能更方便的使用魔术函数__autoload;

 

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇