面向对象知识(4)

类的自动加载

含义:

当某行代码需要一个类的时候,php的内部机制可以做到“自动加载该类文件”,以满足该行需要一个类的这种需求。

 

什么时候需要一个类?

1,new一个对象的时候;

2,使用一个类的静态方法的时候;

3,定义一个类(B)并以另一个类(A)作为父类的时候;

 

条件和要求

1, 当需要一个类的时候,就会自动调用某个函数(默认是__autoload),并传入所需要的类的名字

2, 一个类应该保存到一个独立的“类文件中”:即其中只有该类的定义,没有别的代码;

3,习惯上,类文件的命名要有一定的“规则”,通常是:类名.class.php

4,通常,我们需要将各种类,存储在一些特定的目录中,以方便确定其位置!

5,在该自动加载的函数中,“充分”使用传过来的类名,以构建一个合适的文件路径并载入;

 

自定义自动加载函数:

刚才,__autoload()函数,是系统内部的自动加载函数,我们只是定义其函数体。

 

但:

 

我们可以使用更多函数(自定义的),来实现更灵活的自动加载!

 

基本模式为:

 

spl_autoload_register(“函数1”);          //声明“函数1”作为自动加载函数;

spl_autoload_register(“函数2”);          //声明“函数2”也作为自动加载函数;

.........

然后,就去定义这些函数,跟定义__autoload()函数一样:

function  函数1( $class_name ){

//.......

}

function  函数2( $class_name ){

//.......

}

.............

 

这样,系统就会一次调用这些自动加载函数去加载所需要的类,直到加载成功!

 

 

对象的复制(克隆)

$obj1  =  new  A();

$obj1->p1 = 11;

$obj2  = $obj1;     //值传递

//则,现在有几个对象?——1个对象!

当然:

$obj3  =  & $obj1;

结果,还是一个对象!

 

对象的克隆语法,就是用于将一个对象“制作”双份的语法,类似之前普通数据的“值传递”;

 

语法:

$obj2  =  clone  $obj1;            //这样,就有一个跟$obj1完全一样的新的对象。

 

对象的遍历

对象的遍历,跟数组的遍历,一样!

其实,只能遍历出对象的“实例属性数据”

 

foreach( $对象名  as   $key => $value){

//这里就可以处理$key和$value

//但注意:

1,  $key表示的是对象 的 “属性”,$value是其对应值;

2,  这里能够遍历出来的属性,只能是在该范围中的“可访问属性”(就是要考虑访问控制权限)

}

那,怎么能够将一个对象的所有属性都遍历出来呢?

PHP内置标准类

php语言内部,有“很多现成的类”,其中有一个,被称为“内置标准类”。

这个类“内部”可以认为什么都没有,类似这样:

class  stdclass{ }

其作用,可以用于存储一些临时的简单的数据:

$obj1->pp1 = 1;

$obj1->port = ‘3306’;

 

也可以用于类型转换时用于存储数据,如下节所示

 

其他数据类型转换为对象类型

其他数据类型转换为对象类型,得到的结果是:内置标准类(stdclass)的一个对象!

语法形式为:

$obj1  =  (object) 其他类型数据;

  • 数组转换为对象:数组的键名当作属性名,值为对应值;

注意:数字下标的数据元素,转换为对象后的属性,无法通过对象语法获取,因此不推荐转换。

  • null转换为对象:空对象;

$obj1 = (object)null;

  • 其他标量数据转换为对象:属性名为固定的“scalar”,值为该变量的值:

类型约束

什么叫类型约束?

就是要求某个变量只能使用(接收,存储)某种指定的数据类型;

php属于“弱类型语言”,通常不支持类型约束;

相应的,强类型语言,类型约束却是其“基本特征”。 

php中,只支持局部的部分类型约束

php中,只支持在函数(或方法)的形参上,设定类型的约束目标,形式如下:

function 方法名(【要求使用的类型】$p1 ,  【要求使用的类型】$p2,  ..... ){

//..........

}

说明:

1,定义一个函数(方法)时, 一个形参,可以使用类型约束,也可以不使用;

2,如果使用了类型约束,则对应的该实参数据,就必须是要求的那种类型。

3,能够使用的类型约束,其实非常少,只有以下几种可用:

数组: array,

对象:使用类的名称,表示,传递过来的实参,必须是该类的实例;

接口: 使用接口的名称,表示,传递过来的实参,必须是实现了该接口的类的实例

 

 

 

单例类的加强:禁止克隆

对于一个类的对象,如果使用“clone运算符”,就会克隆出一个跟当前对象完全一样的新对象出来,

并且:

此时还会自动调用该类中的魔术方法:_ _c l o n e ();只要其中有该方法;

 

则,要想实现单例类,就应该对这个单例类的对象“禁止克隆”,做法是:

私有化这个魔术方法:_ _c l o n e ();

 

以下为对单例模式的测试代码:

 

与类有关的其他魔术方法

序列化与反序列化技术

含义:

序列化:

就是将一个变量所代表的“内存”数据,转换为“字符串”形式并持久保存在硬盘上的一种做法。

反序列化:

就是将序列化之后保存在硬盘上的“字符串数据”,恢复为其原来的内存形式的变量数据的一种做法。

 

序列化的做法:

$v1 =  123;          //这是一个变量,代表任意的内存数据

$s1 =  serialize( $v1 );  //将任何类型的变量数据,转换为“字符串”

file_put_contents( ‘要保存的目标文本文件’, $s1);    //将该字符串,保存到一个文件里(就是硬盘数据)

 

反序列化的做法:

$s1 = file_get_contents( ‘保存序列化数据的目标文本文件’);  //从一个文件里读出其中的所有字符

$v1 =  unserialize( $s1 );     //将该字符串数据,反序列化转换为变量(数据)

 

 

举例:

先进行基本数据的序列化:

再来对他们进行反序列化:

 

__sleep():用于对象的序列化:

1,对一个对象进行序列化,只能将其属性数据“保存起来”,而方法被忽略(方法不是数据)

2,对象的序列化的时候,会自动调用该对象所属类的这个魔术方法:__sleep()(前提是有该方法)。

且,此时,该方法必须返回一个数组,数组中是“计划”要进行序列化的属性名;

 

举例:

类文件内容如下:

 

__wakeup:用于对象的反序列化:

1,对一个对象进行反序列化,其实是恢复其原来保存起来的属性数据,而且,此时必然需要依赖该对象原本的所属类;

2,对象在反序列化的时候,会自动调用该对象所属类的这个魔术方法:__wakeup()

 

举例:

 

下面演示可选属性的序列化(通过__sleep):

 

然后,对其对象进行序列,并显示该对象的数据:

 

 

 

然后,在另一个页面中,对其进行反序列化:

 

 

__tostring()魔术方法——比较常用!

含义:

将一个对象“当做”一个字符串来使用的时候,会自动调用该方法,并且在该方法中,可以返回一定的字符串,以表明该对象转换为字符串之后的结果。

 

注意:

如果没有定义该方法,则对象无法当做字符串来使用!!!

 

 

 

__invoke()魔术方法:

将对象当作函数来使用的时候,会自动调用该方法。通常不推荐这么做。

class  A{

function  __invoke(){

echo “<br />我是一个对象呀,你别当我是一个函数来随便调用!”;

}

}

$obj1 = new A();

$obj1();   //此时就会调用类中的方法:__invoke()

其他零碎:

与类有关的魔术常量:

以前学过的魔术常量:

__FILE__

__DIR__

__LINE__

现在:

__CLASS__:  代表当前其所在的类的类名;

__METHOD__:代表其当前所在的方法名;

与类有关的系统函数:

class_exists(“类名”), 判断一个类是否存在(是否定义过)

interface_exists(“接口名”), 判断一个接口是否存在(是否定义过)

get_class( $obj ),           获得某个对象$obj 的所属类

get_parent_class($obj ),               获得某个对象$obj 的所属类的父类

get_class_methods(),            获得一个类的所有方法名,结果是一个数组,里面存储的是这些方法的名称

get_class_vars(),                  获得一个类的所有属性名。结果是一个数组,里面存储的是这些属性的名称get_declared_classes()              获得“整个系统”所定义的所有类名;

 

与对象有关的系统函数:

is_object( $obj ): 判断某个变量是否是一个对象;

get_object_vars( $obj ):获得一个对象的所有属性;结果是一个数组,里面存储的是这些属性的名称

与类有关的运算符:

new,

instanceof:  判断一个“变量”(对象,数据),是否是某个类的“实例”;

示意如下:

class  A {}

class  B {}

class  C extends  A{}

$a1 = new A();

$b1 = new B();

$c1 = new C();

$v1 =  $a1  instanceof  A  ;    //结果是true

$v2 =  $b1  instanceof  A  ;    //结果是false

$v3 =  $c1  instanceof  C  ;    //结果是true

$v4 =  $c1  instanceof  A  ;    //结果是true

——推论:一个类的对象,必然也属于这个类的上级类的对象;

static关键字的新用法和总结:

static这个关键字,也可以像“self”一样,代表“当前类”,用于访问一个类的“静态属性或静态方法”;

但,static,在应用中,更灵活,因此更常见!

因为static,它代表的是“调用”当前方法的类,而不是“其代码所在的类”:

self它就比较死板,只代表这个单词本身所在位置的所在类。

static关键字的使用总结

面向对象编程思想的3个特征:

封装:

无非是一个大的指向思想,目的是为了将一个类设计得更为健壮!

其基本做法是:

尽可能地将一个类的成员私有化,只开放那些必不可少的对外的属性或方法,能private的就不要protected。能protected就不要public

继承:

是面向对象的基本思想和基本做法。

继承是代码重用的一种重要机制。

多态:

多态,就是“多种形态”,其实指的是,现实世界的“丰富多彩的表现形式”,比如:

人在吃饭;

猪在吃食;

鱼在进食;

小鸡啄米;

。。。。

他们都是“吃”这个行为!

在实际代码(应用)中,多态常常有两种表现形式:

1, 不同对象,使用相同的方法,会表现为不同的结果!

2, 同一个对象,使用相同的方法,也可能会表现为不同的结果——这其实是“方法重载现象”

 

posted @ 2016-08-01 15:50  z2168465  阅读(98)  评论(0)    收藏  举报