php-面向对象

 

$this是一个“伪对象”,代表当前所属类的当前对象。

 

一个系统函数:get_class(对象) 作用:获得某个对象的“所属类名”——结果只是一个类名字符串。

 

$class_name = get_class($p1); //结果可能是:”Person” 

静态属性就是:只隶属于类本身——也可以看做是所有对象的“共有数据”。

::$静态属性名

 

类名::静态方法名();

 

注意1:$this在静态方法中不能使用。

静态方法中不应调用非静态方法。

self 含义:代表当前类

使用:通常只能在某个类的某个方法内部代表该类的名称。

 

构造方法

构造方式是类中的一个“特殊”方法,其作用是在实例化一个对象的同时,给该对象的属性赋值,使之一创建完成,就具有了其本身的特有数据(属性值)。

1,该方法名字是固定的,为:__construct();

2,该方法必须是普通方法(不能是静态方法)

3,通常该方法应该是public

4,通常该方法中使用$this这个关键字来对属性进行赋值

5,当new 类名()的时候,其实是在调用该构造方法

6,如果一个类中定义了构造方法,则实例化该类时就会调用该方法,且实例化时的参数需要跟构造方法的参数匹配

 

析构方法

 

构造方法是“创建”对象的时候会自动调用。

 

析构方法是“销毁”对象的时候会自动调用。

 

 

 

说明:

1,析构方法通常不太需要去定义。

2,析构方法不能调用。

3,析构方法不能有形参。

4,析构方法中可以用于清理一些在php代码结束后不能清理的数据,如生成的文件。

对象销毁的几个情形:

脚本程序运行结束,自动销毁;

明确地unset()一个对象变量,则被销毁;

改变对象变量的值,被销毁;

实际上,更本质来说,当一个对象(new 出来的对象)没有任何一个变量指向它的时候,该对象就会被自动销毁——自然,如果整个程序结束,也会销毁。

 

构造方法析构方法在继承中的表现

 

子类中没有定义构造方法时,会自动调用父类的构造方法。因此实例化子类时,需按照父类的构造方法的形式进行。

子类定义了自己的构造方法,则不会自动调用父类的构造方法,但可以手动调用:parent::__construct();

重写override

重写又叫覆盖,就是将从父类继承下来的属性或方法重新“定义”——就是从新写。

访问控制权限

下级的访问控制权限应该不低于上级的访问控制权限:

上级:public  下级:只能public

上级:protected  下级: protected, public

上级:private   下级:private  protected  public——实际此情况无意义。

私有的不能覆盖,而是完全当作自己全新的。

构造方法的重写问题:构造方法不但可以像其他普通方法一样重写,而且,比普通方法更宽松:重写的时候参数可以不一致

最终类final class

通常,一个类,没有特别声明的话,则“别人”就可以随意拿过来使用并对之进行“扩展”——继承。

但是:

如果某个类不希望对其进行扩展,则可以将其声明为“最终类”。

形式:

final  class  类名{ 。。。。类定义。。。。}

 

最终方法final method

 

通常,一个方法,如果没有特别声明,则下级类就可以对其进行“覆盖”(重写)。

 

但是:

 

如果某个方法不希望被下级类覆盖,就可以对其生命为“最终方法”。

 

形式:

 

final  function  方法名(){。。。。方法定义。。。。}

 

PHP中的重载技术

 

通常面向对象语言的重载技术

 

其基本语法是这样的:

 

在一个类中,有多个同名的方法,每个方法的参数不同而已。这种现象就称为“重载”。

 

参数不同可以是:数量个数不同,或类型不同,或顺序不同。

 

比如:

 

class  A{

 

int  function  f1(int  x){......}

 

int  function  f1(int  x,  int  y){.....}

 

int  function  f1(string s   int  m){....}

 

}

 

但,在php中,一个类中,根本就不可以定义多个同名方法——这直接是语法错误。

 

实际上,php中的重载,是另一个“概念”,其指的是:

 

属性重载: 如果使用一个不存在的属性,就会去自动调用类中预先定义好的某个方法以处理数据;

 

方法重载: 如果使用一个不存在的方法,就会去自动调用类中预先定义好的某个方法以处理该行为

属性重载

属性有哪些使用情形?其实跟变量一样,只有4种使用情形:

取值:$v1 = 对象->属性;

赋值:对象->属性 = XX值;

判断是否存在:isset(对象->属性;)

销毁:unset(对象->属性;)

所谓属性重载,就是在面对上述4种情形的属性使用场景中,该对象如果来“应对”的问题。

如果某属性不存在,但在语法中使用如下情形,则会发生:

取值:$v1 = 对象->属性; ===>自动调用类中的__get()方法

赋值:对象->属性 = XX值; ===>自动调用类中的__set()方法

判断是否存在:isset(对象->属性;) ===>自动调用类中的__isset()方法

销毁:unset(对象->属性;) ===>自动调用类中的__unset()方法

前提都是:类中要预先定义好这些方法。

通常,没有的属性,去使用,显然是报错:

方法重载

当使用一个对象调用一个不存在的普通方法的时候,会自动去调用预先定义好的"__call"方法。

其中,该方法必须带2个参数,见下图:

当使用一个对象(类)调用一个不存在的静态方法的时候,会自动去调用预先定义好的"__callStatic"方法。

其中,该方法必须带2个参数。其实跟前面一样!

 

上面所学的几个方法都被称为“魔术方法”:

__get(), __set(),  __isset(), __unset(),  __call(),  __callstatic();

类的自动加载

类的自动加载是指,在外面的页面中,并不需要去“引入”(包含)类文件,但是程序会在需要一个类的时候就自动去“动态加载”该类。

什么叫做“需要一个类”?通常是这样的情况:

1,创建一个对象的时候(new

2,直接使用一个类名(操作静态或静态方法)

做法非常简单:

做法1:使用__autoload魔术函数。

即,“当程序需要一个类”的时候,就会去调用该函数:该函数我们需要自己去定义并在其中写好加载类文件的通用语句:

 

 

 

做法2:使用spl_autoload_register函数

该函数的作用是:用它“注册”(声明)多个可以用来代替__autoload函数作用的函数,语法如下:

spl_autoload_regist(“函数名1”);

spl_autoload_regist(“函数名2”);

.........

自然,其后也得去定义这些函数,并且这些函数的作用跟__autoload一样,不过此时就可以应对“更多的情形”——比如类文件分布在不同的目录中。

 

 

 

对象的复制(克隆)clone

浅克隆:

只能克隆对象中的“非对象非资源”数据:

 

但,如果对象中的属性存储的是“对象”类型,则就可以看到克隆不完全的情形,如下:

 

 

 

 

可见,修改了o1中的b1数据,发现o2种的b1数据也跟着改变了——克隆不完全。

 

我们可以使用“深克隆”来解决:

php中,默认克隆是浅克隆

要想实现深克隆(一个对象的所有属性数据都彻底实现了“复制”),就需要对该对象类使用魔术方法:

__clone(),并在里面来实现深度克隆——人为去复制浅克隆复制不了数据。

则刚才的代码,改进如下:

 

 

 

 

 

 

 

 

对象遍历

对象也可以可以使用foreach语句进行便利,有两点注意:

1,只能便利属性。

2,只能便利“看得到”的属性——代码所在范围可访问。

在外面遍历:

 

 

 

 

可见,此时protectedprivate属性都没有遍历出来。

如果需要全部遍历,则改造为:

 

 

 

 

 

 

 

 

 

将数据转换为对象

转换基本语法:(目标类型)数据;

对象转换为对象:没有变化;

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

但通常,如果数数字下标,则其对应属性 并不方便操作(->)

所以通常就适合于纯字符下标的数组。

 

 

 

与类有关的魔术常量:

__CLASS__,:获取其所在的类的类名。

__METHOD__:获取其所在的方法的方法名。

class  A{

function  f1(){

echo __CLASS__ //输出“A

echo __METHOD__//输出“f1

//注意:get_class()也可以得到类名,但其必须有个“对象”

}

}

 

 

 

 

 

 

 

 

 

__tostring()方法

当把一个对象当作一个“字符串”来看待(处理)的时候,会自动调用该魔术方法。

通过该方法,可以返回“合适”的字符串,也可以认为就是对象转换为字符串的结果。

如果没有改方法,会出错。

对象不能直接当字符串使用:

__invoke()方法

对象当作一个“方法”(函数)的时候,会自动调用该魔术方法。

比如:

$v1 = $obj(1,2); //$obj其实是一个对象,这里就相当于将对象当函数用

 

 

 

一些有关类和对象的系统函数和运算符

class_exists(), :判断某个类是否存在(定义过)

interface_exists(), :判断接口是否存在

get_class():获取某个对象的“所属类名”

get_parent_class(), :获取某个对象的“所属父类的类名”

get_class_methods(), :获取一个类的所有方法,返回一个索引数组,就是这些方法的名字。

get_class_vars(), :获取一个类的所有属性,返回一个数组,下标为属性名,值为属性值。

get_declared_classes():获得所有声明过的类(含系统中的类)

is_object():判断是否对象

get_object_vars():获得对象的所有属性,返回一个数组,下标为属性名,值为属性值

运算符:

new

instanceof: 判断一个对象是否是某个类的“实例”

 

posted @ 2019-09-23 14:37  ggsa202008  阅读(162)  评论(0编辑  收藏  举报