PHP面向对象
PHP面向对象:魔术方法
#### 1. \__construct >大多数类都有一种称为构造函数的特殊方法。当创建一个对象时,它将自动调用构造函数,也就是使用new这个关键字来实例化对象的时候自动调用构造方法。在一个类中只能声明一个构造方法,而是只有在每次创建对象的时候都会去调用一次构造方法,不能主动的调用这个方法,所以通常用它执行一些有用的初始化任务。比如对成属性在创建对象的时候赋初值。 ```php <? //创建一个人类 class Person { //下面是人的成员属性 var $name; //人的名子 var $sex; //人的性别 var $age; //人的年龄 //定义一个构造方法参数为姓名$name、性别$sex和年龄$age function __construct($name, $sex, $age) { //通过构造方法传进来的$name给成员属性$this->name赋初使值 $this->name = $name; //通过构造方法传进来的$sex给成员属性$this->sex赋初使值 $this->sex = $sex; //通过构造方法传进来的$age给成员属性$this->age赋初使值 $this->age = $age; } //这个人的说话方法 function say() { echo "我的名子叫:" . $this->name . " 性别:" . $this->sex . " 我的年龄是:" . $this->age; } } ``` #### 2. \_destruct >析构函数允许在销毁一个类之前执行的一些操作或完成一些功能,比如说关闭文件, 释放结果集等,析构函数会在到某个对象的所有引用都被删除或者当对象被显式销毁时执行,也就是对象在内存中被销毁前调用析构函数。与构造函数的名称类似, 一个类的析构函数名称必须是\__destruct( )。析构函数不能带有任何参数。 ```php class Person{ function __destruct() { //主要用在关闭一些资源句柄 } } ``` #### 3. \__call 处理调用错误 >在程序开发中,如果在使用对象调用对象内部方法时候,调用的这个方法不存在那么程序就会出错,然后程序退出不能继续执行。那么可不可以在程序调用对象内部 不存在的方法时,提示我们调用的方法及使用的参数不存在,但程序还可以继续执行,这个时候我们就要使用在调用不存在的方法时自动调用的方 法“\__call()”。 ```php <?php //这是一个测试的类,里面没有属性和方法 class Test { //调用不存的方法时自动调用的方法,第一个参数为方法名,第二个参数是数组参数 function __call($function_name, $args) { print "你所调用的函数:$function_name(参数:"; print_r($args); echo ")不存在!<br> "; } } ``` #### 4. \__get >这个方法用来获取私有成员属性值的,有一个参数, 参数传入你要获取的成员属性的名称,返回获取的属性值, 这个方法不用我们手工的去调用, 是在直接获取私有属性的时候自动调用的。因为私有属性已经被封装上了,是不能直接获取值的(比如:”echo $p1->name” 这样直接获取是错误的),但是如果你在类里面加上了这个方法,在使用”echo $p1->name” 这样的语句直接获取值的时候就会自动调用\__get($property_name)方法,将属性name传给参数$property_name,通过这 个方法的内部执行,返回我们传入的私有属性的值。 ```php class man extends Person { public function __construct($id) { $this->getName($id); } public function __get($field) { if($field == 'name') { return $this->username; } } } ``` #### 5. \__set >这个方法用来为私有成员属性设置值的, 有两个参数,第一个参数为你要为设置值的属性名,第二个参数是要给属性设置的值,没有返回值。这个方法同样不用我们手工去调用,是在直接设置私有属性值的 时候自动调用的,同样属性私有的已经被封装上了, 如果没有\__set()这个方法,是不允许的, 比如:”$this->name=’zhangsan’,这样会出错,但是如果你在类里面加上了\__set($property_name, $value)这个方法,在直接给私有属性赋值的时候,就会自动调用它,把属性比如name传给$property_name, 把要赋的值”zhangsan”传给$value,通过这个方法的执行,达到赋值的目的, 为了不传入非法的值, 还可以在这个方法给做一下判断。 #### 6. \__isset() 方法 >在看这个方法之前我们看一下“isset()”函数的应用,isset()是测定变量是否设定用的函数,传入一个变量作为参数,如果传入的变量存在则传回true,否则传回false。那么如果在一个对象外面使用“isset()”这个函数去测定对象里面的成员是否被设定可不可以用它呢? 分两种情况,如果对象里面成员是公有的,我们就可以使用这个函数来测定成员属性,如果是私有的成员属性,这个函数就不起作用了,原因就是因为私有的被封装了,在外部不可见。那么我们就不可以在对象的外部使用“isset()”函数来测定私有成员属性是否被设定了呢?可以,你只要在类里面加上一个“\__isset()”方法就可以了,当在类外部使用”isset()”函数来测定对象里面的私有成员是否被设定时,就会自动调用类里面的“\__isset()”方法了帮我们完成这样的操作,“\__isset()”方法也可以做成私有的。 你可以在类里面加上下面这样的代码就可以了: ```php private function __isset($nm){ echo "当在类外部使用isset()函数测定私有成员$nm时,自动调用<br />"; return isset($this->$nm); } ``` #### 7. \__unset()方法 >看这个方法之前呢,我们也先来看一下“unset()”这个函数,“unset()”这个函数的作用是删除指定的变量且传回true,参数为要删除的变量。那么如果在一个对象外部去删除对象内部的成员属性用“unset()”函数可不可以呢, 也是分两种情况,如果一个对象里面的成员属性是公有的,就可以使用这个函数在对象外面删除对象的公有属性,如果对象的成员属性是私有的,我使用这个函数就没有权限去删除,但同样如果你在一个对象里面加上“\__unset()”这个方法,就可以在对象的外部去删除对象的私有成员属性了。在对象里面加上了“\__unset()”这个方法之后,在对象外部使用“unset()”函数删除对象内部的私有成员属性时,自动调用“\__unset()”函数来帮我们删除对象内部的私有成员属性,这个方法也可以在类的内部定义成私有的。在对象里面加上下面的代码就可以了: ```php private function __unset($nm){ echo "当在类外部使用unset()函数来删除私有成员时自动调用的<br />"; unset($this->$nm); } ``` #### 6. \__sleep \__wakeup() >在PHP5中有两个魔术方法\__sleep()方法和\__wakeup()方法,在对象串行化的时候,会调用一个\__sleep()方法来完成一 些睡前的事情;而在重新醒来,即由二进制串重新组成一个对象的时候,则会自动调用PHP的另一个函数\__wakeup(),做一些对象醒来就要做的动作。 \__sleep()函数不接受任何参数, 但返回一个数组,其中包含需要串行化的属性。末被包含的属性将在串行化时被忽略,如果没有\__sleep()方法,PHP将保存所有属性。 ```php <? class Person{ //下面是人的成员属性 var $name; //人的名子 var $sex; //人的性别 var $age; //人的年龄 //定义一个构造方法参数为属性姓名$name、性别$sex和年龄$age进行赋值 function __construct($name = "", $sex = "", $age = "") { $this->name = $name; $this->sex = $sex; $this->age = $age; } //这个人可以说话的方法, 说出自己的属性 function say() { echo "我的名子叫:" . $this->name . " 性别:" . $this->sex . " 我的年龄是:" . $this->age . "<br>"; } //指定串行化时把返回的数组中$name和$age值串行化,忽略没在数组中的属性$sex function __sleep() { $arr = array("name", "age"); // 此时,属性$sex将被删除!!! return($arr); } //重新生成对象时,并重新赋值$age为40 function __wakeup() { $this->age = 40; } } $p1 = new Person("张三", "男", 20); //把一个对象串行化,返一个字符串,调用了__sleep()方法,忽略没在数组中的属性$sex $p1_string = serialize($p1); echo $p1_string . "<br>"; //串行化的字符串我们通常不去解析 $p2 = unserialize($p1_string); //反串行化形成对象$p2重新赋值$age为40 $p2->say(); ?> 上例输出值为: O:6:"Person":2:{s:4:"name";s:4:"张三";s:3:"age";i:20;} 我的名子叫:张三 性别: 我的年龄是:40 ``` #### 7. \__toString >“\__toString()”方法也是一样自动被调用的,是在直接输出对象引用时自动调用的, 前面我们讲过对象引用是一个指针,比如 说:“$p=new Person()“中,$p就是一个引用,我们不能使用echo 直接输出$p,这样会输 出Catchable fatal error: Object of class Person could not be converted to string这样的错误,如果你在类里面定义了“\__toString()”方法,在直接输出对象引用的时候,就不会产生错误,而是自动调用 了”\__toString()”方法, 输出“\__toString()”方法中返回的字符,所以“\__toString()”方法一定要有个返回值(return 语句)。 ```php <?php class TestClass { public $foo; public function __construct($foo) { $this->foo = $foo; } //定义一个__toString方法,返加一个成员属性$foo public function __toString() { return $this->foo; } } $class = new TestClass('Hello'); //直接输出对象 echo $class; ``` #### 8. \__clone >有的时候我们需要在一个项目里面,使用两个或多个一样的对象,如果你使用“new”关键字重新创建对象的话,再赋值上相同的属性,这样做比较烦琐而且也容易出错,所以要根据一个对象完全克隆出一个一模一样的对象,是非常有必要的,而且克隆以后,两个对象互不干扰。 PHP定义了一个特殊的方法名“\__clone()”方法,是在对象克隆时自动调用的方法,用“\__clone()”方法将建立一个与原对象拥有相同属 性和方法的对象,如果想在克隆后改变原对象的内容,需要在\__clone()中重写原本的属性和方法, “\__clone()”方法可以没有参数,它自 动包含$this和$that两个指针,$this指向复本,而$that指向原本; #### 9. \__autoload >\__autoload 函数,它会在试图使用尚未被定义的类时自动调用。通过调用此函数,脚本引擎在 PHP 出错失败前有了最后一个机会加载所需的类。 注意: 在\__autoload 函数中抛出的异常不能被 catch 语句块捕获并导致致命错误。 ```php <?php function __autoload($classname){ require_once $classname . '.php'; } //MyClass1类不存在时,自动调用__autoload()函数,传入参数”MyClass1” $obj = new MyClass1(); //MyClass2类不存在时,自动调用__autoload()函数,传入参数”MyClass2” $obj = new MyClass2(); //另一种写法 if (function_exists('spl_autoload_register')){ spl_autoload_register(array('core', 'autoload')); }else{ function __autoload($class){ return core::autoload($class); } } ```
顶部
收展
底部
[TOC]
目录
PHP面向对象:基本概念
PHP面向对象:三大特征
PHP面向对象:魔术方法
PHP面向对象:对象串行化
PHP面向对象:访问类型
PHP面向对象:关键字
PHP面向对象:类的应用
PHP面向对象:抽象方法和抽象类
PHP面向对象:接口(interface)
相关推荐
PHP底层
PHP应用
PHP工具类
PHP编程经验
PHP框架