<?php // 父类 class Animal { public $name; public $age; // 构造函数,使用new操作符生成实例的时候自动调用 function __construct($name, $age) { $this->name = $name; $this->age = $age; } public function show() { echo $this->name . ' ' . $this->age . '<br/>' ; } // 析构函数,对象销毁的时候自动调用 function __destruct() { echo 'object destroyed' . '<br/>'; } } // 子类 class Dog extends Animal { public $legs; function __construct($name, $age, $legs) { // 调用父类的方法 parent::__construct($name, $age); $this->legs = $legs; } public function showLegNumber() { echo $this->legs . '<br/>'; } } $myDog = new Dog('candy', 10, 4); $myDog->show(); $myDog->showLegNumber(); $myDog = null; $hisDog = new Dog('sally', 5, 4); $hisDog->show(); ?>
在执行对象方法时,PHP将会自动定义一个$this的特殊变量(类似js的this),该变量表示对对象本身的引用,通过使用$this变量和'->'符号可以引用对象本身的所有属性和方法(类似js的this.)。
析构函数是一个名为__destruct()的函数,它是在对象被注销时所调用的。通常PHP会在所有请求都结束时自动释放该对象所占有的资源,所以析构函数显的并不是那么重要。但是在某些情况下还是有用处的,如释放指定的资源或者记录日志信息。在上例中,就算没有将$hisDog对象赋值为null,在脚本执行结束时也将会自动调用其析构函数。
类的继承需使用关键字extends,通常在PHP中使用parent表示父类,常用于访问父类的方法和属性;使用self表示子类,常用于访问当前类中的常量、静态变量和方法。
在PHP中,存在着全局常量,使用define关键字定义。而在PHP5中,还可以在类中定义常量。类的常量不属于任何的类的实例,只属于类的本身,且不可修改。定义类的常量很简单,只需要使用const关键字进行定义即可。对于类的常量的引用分为两种情况:一种是在类的内部进行引用,另一种是在类的外部进行引用。不管是何时进行引用,都需要使用范围解析操作符(::)。
<?php class Color { const RED = 'red'; const BLUE = 'blue'; const WHITE = 'white'; function getWhite() { // 内部引用 return self::WHITE; } } // 外部引用 echo Color::RED; $obj = new Color(); echo $obj->getWhite(); ?>
每一个类的实例都有其所有属性和方法的拷贝,但类还可以定义静态属性和静态方法。静态属性(方法)和类的常量一样,只属于类的本身,通过关键字static定义。访问方式和类的常量一样。
<?php class myClass { static $num = 0; function __construct() { self::$num++; } // 统计该类实例化的个数 static function printNum() { echo self::$num . '<br/>'; } } myClass::printNum(); $a = new myClass(); myClass::printNum(); $b = new myClass(); myClass::printNum(); $c = new myClass(); myClass::printNum(); ?>
在使用面向对象的程序设计模式进行开发时,最为重要的一点就是封装和对象属性的访问保护,而访问修饰符就是因此诞生的。通常对于类属性和方法,访问保护都是通过3个关键字来实现的:public、protected和private。在开发时,需要制定属性或方法的访问权限,为了向下兼容, 定义方法 时未指定访问权限将自动设置为public(如定义属性为指定会报错)。
指定为public的类属性和方法为公共的属性和方法,可以在任何作用域内访问。在对象外可以采用对象名->属性名(方法名)访问,在对象内部可以用$this->属性名(方法名)访问。若一个类从该类继承,则这个类的对象的外部和内部访问该类属性或者方法可以采用相同的方式。
指定为protected的类属性和方法只能够在对象内部使用,即采用$this->(受保护)属性名(变量名)的方式进行访问。若一个类从该类继承,则受保护的类属性和方法也可以在类的对象的方法中采用如上方式访问。
指定为private的类属性和方法和protected类似,只能在对象内部访问,同时也不能在继承类的实例对象中进行访问,因为私有属性和方法在继承的类中时看不到的。
总结:public修饰定义可以从任何位置访问到类属性和方法;protected修饰符定义只能在类的内部及该类子类中(继承)进行访问;private修饰符定义只能在类的内部进行访问。
在PHP中,除了提供静态方法外,还提供了几个有用的魔术方法。这里的魔术方法包括前面所讲的构造函数__construct()、析构函数__destruct(),以及字符串转换函数__toString()和克隆函数__clone()。
当用echo或者print输出一个对象时,将自动调用__toString()方法(不觉得比var_dump()好用)
<?php class Child { public $name; public $age; function __construct($name, $age) { $this->name = $name; $this->age = $age; } function __toString() { return $this->name . ' ' . $this->age . '<br/>'; } } $myChild = new Child('hanzichi', 10); print $myChild; echo $myChild; var_dump($myChild); ?>
在实际应用中,除了采用new关键字创建对象外,还可以使用clone关键字实现对象克隆,所克隆的对象将拥有原对象的所有属性。
<?php class Child { public $name; public $age; function __construct($name, $age) { $this->name = $name; $this->age = $age; } function show() { echo $this->name . ' ' . $this->age . '<br/>'; } } $myChild = new Child('hanzichi', 10); $hisChild = clone $myChild; $hisChild->show(); // hanzichi 10 ?>
有些时候我们并不需要克隆完全一样的对象,这时我们可以在类中定义__clone方法,克隆的时候会自动调用。
<?php class Child { public $name; public $age; function __construct($name, $age) { $this->name = $name; $this->age = $age; } function __clone() { $this->name = 'candy'; } function show() { echo $this->name . ' ' . $this->age . '<br/>'; } } $myChild = new Child('hanzichi', 10); $hisChild = clone $myChild; $hisChild->show(); // candy 10 ?>