高级点的php书,PHP的一些高级特性

自定义__clone()复制对象

class Person{

public $name;

public function __construct($name) {

$this->name = $name;

}

}

$first = new Person("zhangsan");

$second = $first;

如上例,PHP4时代$second和$first是两个完全不同的对象,php5之后$second和$first指向同一个对象。但对于基本数据类型显然不是引用复制。

//PHP 5.2.17 (cli) (built: May 26 2015 16:23:47)

$second->name = "lisi";

var_dump($first === $second); //true

var_dump($second->name); //lisi

var_dump($first->name); //lisi

$third = array(

"hello" => "world",

); //分配数组的空间0x0001,分配变量$third内存,并指向0x0001

$fourth = $third; //分配变量$fourth内存,并指向同一地址0x0001,引用计数加1

var_dump($fourth === $third); //true,内容相同,内容地址也相同

$fourth['hello'] = "fuck"; //变量改变,重新copy一份出来,给$fourth指向,并修改引用计数

var_dump($fourth === $third); //false,已经是不同的内容,不同的地址

这就很尴尬了,虽然引用复制较为节省空间,但有时我们希望对象的复制是值copy,各自保留各自的副本。php提供的clone关键字能够解决该问题。

$first = new Person("zhangsan");

$second = clone $first; //各自有一份TestPHP的副本

var_dump($first === $second); //false,地址不同

$second->name = "lisi"; //修改的是自己的TestPHP对象内容

var_dump($second->name); //lisi

var_dump($first->name); //zhangsan

尴尬的事又出现了,一个clone把事都办了,那还有啥高级特性?我们如果要自定义对象的copy呢?比如我希望在复制Person的时候,除id以外的信息,而id要初始化成0。那就需要自定义对象的clone了。

class Person{

public $id;

public $name;

function __construct($id,$name) {

$this->id = $id;

$this->name = $name;

}

public function __clone() {

$this->id = 0;

}

}

$first = new Person("1", "zhangsan");

$second = clone $first;

var_dump($second->id . " | " . $second->name); //0 | zhangsan

var_dump( $first->id . " | " . $first->name ); //1 | zhangsan

这时Account加入了战斗,问题又出现了。

class Account {

public $balance;

function __construct($balance) {

$this->balance = $balance;

}

}

class Person {

public $id;

public $name;

public $account;

function __construct($id, $name, Account $account) {

$this->id = $id;

$this->name = $name;

$this->account = $account;

}

public function __clone() {

$this->id = 0;

}

}

$first = new Person("1", "zhangsan", new Account(100));

$second = clone $first;

$first->account->balance += 10000;

var_dump($first->account->balance); // 10100

var_dump($second->account->balance); //10100

$first、$second初始化账户上应该又100元,现在给$first充了10000,结果$second的账户上也被加了10000,,因为在clone Person对象时,account变量的复制仍然是引用复制,导致问题,需修改__clone方法

function __clone() {

$this->id = 0;

$this->account = clone $this->account;

}

__autoload()与spl_autoload_register()实现自动加载

PHP5引入了__autoload()拦截器方法实现类文件的自动加载,需要自定义加载函数,其实就是说清楚在php执行过程中,遇到未定义的类,到哪儿取找该类的实现文件。

$testLoad = new TestLoad(); //Fatal error: Class 'TestLoad' not found in XXXXX

$testLoad->say();

但是如果自定义实现了__autoload()方法,方法需要传递className作为参数名,然后找到TestLoad类的实现,加载类,实例化,调用say()方法就ok。

function __autoload($className) {

require_once "$className.php"; //自己定义,想加载什么文件、想到哪儿加载文件都是自己定义

}

$testLoad = new TestLoad();

$testLoad->say(); //hello,world

TestLoad类的实现

class TestLoad {

public function say() {

echo "hello,world" . PHP_EOL;

}

}

spl_autoload_register()方法又是干啥的呢? 这么理解,__autoload()方法是正规军,系统是认识它的,你只要敢定义它,就能实现类的自动加载。但是如果地方军呢?比如我想起个名字叫XX()的加载函数,就需要使用spl_autoload_register()去登记注册告诉系统这是自己人,以后遇到未定义类的时候,找XX就行了。

function myLoad($className) {

require_once "$className.php";

}

spl_autoload_register("myLoad");

$testLoad = new TestLoad();

$testLoad->say();

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值