有了前面的基础知识,就可以开始学习 PHP 中的面向对象了。
类的定义
简单来说定义一个类的方式是这样的:
<?php
class Person {
public $name = 'Meniny';
public function getName() {
return $this->name;
}
}
?>
类的实例化
那么创建这个类的实例则是这样的:
<?php
$person = new Person();
?>
或者兜个圈子:
$clsName = 'Person';
$person = new $clsName();
访问控制
上面用到的访问控制关键字,和主流语言没什么不同:
-
public : 公开
-
protected : 受保护
-
private : 私有
注意: 属性变量必须声明访问控制,方法可以省略方法控制声明,默认为 public
<?php
class Guy {
public $name = 'Tom';
protected $age = 20;
private $wealth = 100000;
}
$guy = new Guy();
echo $guy->name; // ✔ 正确
echo $guy->age; // ✗ 错误
echo $guy->wealth; // ✗ 错误
?>
静态方法
此外,你还可以使用 static
关键字来修饰类中的方法使其成为静态方法,静态方法不需要实例对象,可以通过类名调用,操作符为双冒号(::
)。
<?php
class Pet {
public static function getOwner() {
return 'Meniny';
}
}
echo Pet::getOwner();
?>
或者再兜个圈子:
$func = 'getOwner';
$cls = 'Pet';
echo $cls::$func();
类的继承
PHP 中的类同样可以集成,通常实现一个类的集成是这样的:
<?php
class Creature {
// ....
}
class Human extends Creature {
// ....
}
?>
构造与析构
在类中我们可以使用 __construct()
定义构造函数,供该类实例化时调用。
注意,
__construct()
前面是两个连续的下划线(_
)
<?php
class Car {
function __construct() {
print "construct()";
}
}
$car = new Car();
?>
在执行上面 $car = new Car();
代码时,构造函数将会被调用,因此在控制台应当有字符串 construct()
输出。
如果定义了构造函数,那么父类中的构造函数将不会再被调用,除非进行显式调用。
<?php
class Creature {
function __construct() {
print "Some Creature\n";
}
}
class Human extends Creature {
function __construct() {
parent::__construct();
print "Human\n";
}
}
$human = new Human();
?>
类似的,我们还可以使用 __destruct()
定义析构函数,供对象销毁时调用。
<?php
class Car {
function __construct() {
print "construct()";
}
function __destruct() {
print "destruct()";
}
}
$car = new Car(); // 输出"construct()"
unset($car); // 输出"destruct()"
?>
因为 PHP 代码之行结束后主动回收和销毁对象,因此通常来说,很少显式对对象进行销毁操作。
重载
PHP 中的重载指的是属性和方法的动态创建。
属性重载
属性重载通过 __set
,__get
,__isset
,__unset
来实现。
<?php
class Car {
private $ary = array();
public function __set($key, $val) {
$this->ary[$key] = $val;
}
public function __get($key) {
if (isset($this->ary[$key])) {
return $this->ary[$key];
}
return null;
}
public function __isset($key) {
if (isset($this->ary[$key])) {
return true;
}
return false;
}
public function __unset($key) {
unset($this->ary[$key]);
}
}
$car = new Car();
// 动态创建
$car->name = 'BMW';
echo $car->name;
?>
方法重载
方法重载通过 __call
来实现。如果调用不存在的方法的将转为参数调用 __call
方法,如果调用不存在的静态方法用 __callStatic
重载。
<?php
class Car {
public $price = 100000;
public function __call($name, $args) {
if ($name == 'raiseThePrice') {
$this->price += 2000;
}
}
}
$car = new Car();
// 调用不存在的方法
$car->raiseThePrice();
echo $car->price;
?>
克隆对象
在某些情况下,我们可能需要将某个对象复制一份使用,这时我们可以使用 clone
关键字来进行克隆操作,通过调用 __clone()
方法设置属性。
<?php
class Sheep {
public $name = 'Dolly';
public function __clone() {
$obj = new Sheep();
$obj->name = $this->name;
}
}
$s1 = new Sheep();
$s1->name = 'Dolly the Sheep';
$s2 = clone $s1;
var_dump($s2);
?>
对象序列化与反序列化
-
要实现对象序列化,需要通过
serialize
方法进行操作。 -
要实现对象反序列化,需要通过
unserialize
方法进行操作。
<?php
class Secret {
public $name = 'the Secret';
}
$a = new Secret();
// 序列化
$str = serialize($a);
echo $str."\n";
// 反序列化
$b = unserialize($str);
var_dump($b);
?>
对象比较
对于同一个类的两个实例,要判断是否所有属性都相等,可以使用 ==
运算符。
对于两个变量是否引用字同一对象时,可以使用 ===
运算符。