PHP面向对象3

clone与__clone()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php
class Person{
protected $name;
public function __construnt($name){
$this->name=$name;
}
public function show(){
echo $this->name;
}
public function __clone(){
echo "对象被克隆了<br>";
}
}

$per1 = new Person('胡浩');
var_dump($per1);
echo '<br>';
$per2 = $per1;
var_dump($per2);
echo '<br>';
$per3 = clone $per1;
var_dump($per3);
?>
object(Person)#1 (1) { ["name":protected]=> NULL }
object(Person)#1 (1) { ["name":protected]=> NULL }
对象被克隆了
object(Person)#2 (1) { ["name":protected]=> NULL }

创建新对象的方法有两个:
1、 实例化
2、 clone
当执行clone命令的时候,会自动调用__clone()函数

单例模式

一个类只能有一个对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?php
//三私一公
class Student{
// 私有的静态属性保存当前实例
private static $instance;
// 私有的构造函数阻止在类的外部实例化
private function __construnct(){}
// 私有的__clone() 用来阻止在类外部clone对象
private function __clone(){}
// 公有的静态方法用来获取实例
public static function getInstance(){
if (!self::$instance instanceof self) {
self::$instance = new self;
}
return self::$instance;
}
}

//单例模式
$stu1 = Student::getInstance();
$stu2 = Student::getInstance();

var_dump($stu1);
echo "<br>";
var_dump($stu2);
?>
object(Student)#1 (0) { }
object(Student)#1 (0) { }

instanceof用来判断变量是否属于某种数据类型

项目层面的单例模式(一个项目中有一组单例模式)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<?php
class DB1 {
private static $instance;
private function __construct() {
}
private function __clone() {
}
public static function getInstance() {
if(!self::$instance instanceof self) //实例的数据类型不是Student类型的
self::$instance=new self;
return self::$instance;
}
}
class DB2 {
private static $instance;
private function __construct() {
}
private function __clone() {
}
public static function getInstance() {
if(!self::$instance instanceof self) //实例的数据类型不是Student类型的
self::$instance=new self;
return self::$instance;
}
}
class DB3 {
private static $instance;
private function __construct() {
}
private function __clone() {
}
public static function getInstance() {
if(!self::$instance instanceof self) //实例的数据类型不是Student类型的
self::$instance=new self;
return self::$instance;
}
}
//项目层面的单例模式
function getInstance($db_name) {
static $array=array();
if(!isset($array[$db_name]))
$array[$db_name]=$db_name::getInstance($db_name);
return $array[$db_name];
}
//测试
$db1=getInstance('DB1');
$db2=DB1::getInstance();
var_dump($db1,$db2);
?>

object(DB1)#1 (0) { } object(DB1)#1 (0) { }

工厂模式

传递不同的参数获取不同的对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?php 
class ProductA {
public function getProduct() {
echo '这是A商品<br>';
}
}
class ProductB{
public function getProduct() {
echo '这是B商品<br>';
}
}
//工厂模式
class ProductFactory {
public static function create($num) {
switch($num) {
case 1:
return new ProductA();
case 2:
return new ProductB;
}
return null;
}
}
$objA=ProductFactory::create(1);
$objB=ProductFactory::create(2);
$objA->getProduct();
$objB->getProduct();
?>
这是A商品
这是B商品

策略模式

传递不同的参数,调用不同的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?php 
//策略模式
interface IStrategy {
function ontheway();
}

class Walk implements IStrategy {
public function ontheway() {
echo '走着去<br>';
}
}
class Bike implements IStrategy{
public function ontheway() {
echo '骑车去<br>';
}
}
class Bus implements IStrategy {
public function ontheway() {
echo '坐巴士去<br>';
}
}
//传递不同的参数,调用不同方法
class Strategy {
public function getWay(IStrategy $obj) {
$obj->ontheway();
}
}
$obj=new Strategy();
$obj->getWay(new Walk);
$obj->getWay(new Bike);
$obj->getWay(new Bus);
?>
走着去
骑车去
坐巴士去

魔术方法

__tostring()

当把对象当成字符串调用时自动执行

1
2
3
4
5
6
7
8
9
10
11
12
<?php 
class Student{
//当把对象当成字符串调用时自动执行
public function __toString(){
return "这是一个学生对象";
}
}

$stu=new Student;
echo $stu;
?>
这是一个学生对象

__invoke()

当把对象当成函数调用的时候自动执行

1
2
3
4
5
6
7
8
9
10
11
<?php 
class Student{
//当把对象当成函数调用的时候自动执行
public function __invoke($args){
echo "这是一个学生对象,你传递的参数是:".$args;
}
}
$stu = new Student();
$stu('tom')
?>
这是一个学生对象,你传递的参数是:tom

__set()、__get()

set():当给无法访问的属性赋值的时候自动调用 get():当获取无法访问的属性值的时候自动调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php 
class Student{
private $name;
// 当给无法访问的属性赋值时自动调用
public function __set($key,$value){
$this->$key=$value;
}
//当获取无法访问的属性值的时候自动调用
public function __get($key){
return $this->$key;
}
}

$stu = new Student();
$stu->name='tom';
echo $stu->name;
?>
tom

__unset()、__isset()

unset():当销毁无法访问的属性的时候自动调用 isset():当判断无法访问的属性是否存在时自动调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php 
class Student{
private $name;
private $sex;
private $array=array('name','sex');
// 当销毁无法访问的属性的时候自动调用
public function __unset($key){
unset($this->$key);
}
// 当判断无法访问的属性时自动调用
public function __isset($key){
return in_array($key,$this->array);
}
}

$stu=new Student();
echo isset($stu->name)?'yes':'no';
echo "<br>";
echo isset($stu->sss)?'yes':'no';
?>
yes
no

__call()、__callstatic()

call():当调用无法访问的普通方法时候自动调用 callstatic():当调用无法访问的静态方法时候自动调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?php 
class Student{
/**
* 当调用无法访问的方法时自动调用
* @param $fn_name string 传递方法名
* @param $fn_args array 传递参数数组
*/
public function __call($fn_name,$fn_args){
echo "不能调用".$fn_name."方法<br>";
var_dump($fn_args);
//echo implode(',',$fn_args);
}
// 当输出静态方法调用一个无法访问的方式时自动调用
public static function __callStatic($fn_name,$fn_args){
echo "<br>不能调用静态".$fn_name.'方法<br>';
}
}

$stu = new Student();
$stu->show(10,20);
Student::test();
?>
不能调用show方法
array(2) { [0]=> int(10) [1]=> int(20) }
不能调用静态test方法

Iterator(迭代器)

Iterator是迭代器,是PHP内置的接口,用来遍历类中的某个属性。迭代器中有5个抽象方法

  1. Iterator::current -返回当前元素
  2. Iterator::key -返回当前元素的键
  3. Iterator::next -向前移动到下一个元素
  4. Iterator::rewind -返回到迭代器的第一个元素
  5. Iterator::valid -检查当前位置是否有效
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<?php 
//学生类
class Student {
private $name;
public function __construct($name) {
$this->name=$name;
}
public function __get($key) {
return $this->$key;
}
}
//班级类
class MyClass implements Iterator {
private $stu_list=array(); //学生数组
public function addStu(Student $stu) {
$this->stu_list[]=$stu;
}
//指针复位到数组的第一个元素
public function rewind() {
reset($this->stu_list);
}
//检查当前指针的位置是否合法
public function valid() {
return key($this->stu_list)!==null;
}
//返回当前值
public function current() {
return current($this->stu_list);
}
//返回当前键
public function key() {
return key($this->stu_list);
}
//指针下移一位
public function next() {
next($this->stu_list);
}
}
//创建班级
$class=new MyClass;
$class->addStu(new Student('tom'));
$class->addStu(new Student('berry'));
$class->addStu(new Student('Ketty'));
//遍历班级,就是遍历学生数组
foreach($class as $stu) {
echo $stu->name,'<br>';
}
?>
tom
berry
Ketty

数组的序列化(serialize)和反序列化(unserialize)

对象的序列化和反序列化