分享

PHP教程(18)工厂单例模式+继承链+静态方法+php重载+序列化+魔术方法+对象遍历

 知识书馆 2022-07-17 发布于广东

回顾

面向对象:自动加载(__autoload),类常量访问(范围解析操作符),静态(属性和方法:self

设计模式:单例模式(三私一公),工厂模式

面向对象三大特性:封装,继承和多态(PHP不支持)

PHP继承:extends(对象继承:属性和非私有方法)


PHP继承

方法重写

子类拥有与父类同名的方法。

除了私有的属性和方法之外,系统一律都是去子类中查找属性和方法,但是如果对应的属性和方法是私有的,那么系统一定要去判断$this所代表的上下文(类环境),在哪个类就访问哪个类的私有属性和方法。

重写的原则:被重写的方法的访问权限一定要比原来的方法的权限要大(Open)。

PHP继承链

php中不支持一个类继承自多个父类。

在有些语言中可以实现多继承:class A extends B,CPHP中不行)

PHP中可以通过继承链(链式继承)来实现子类继承多个“父类”。

静态在继承中的使用

静态的东西属于类,类其实在结构有类似继承概念,所以静态的内容也可以遵循继承的传统去跨类使用。

parent关键字

如果子类中重写了父类的方法,那么父类的方法就不再会被调用,但是有时候需要父类的方法也执行,就需用使用parent关键字:

在被重写的方法之内:parent::父类的同名方法()

特殊类

有时候不希望自己写的类被别人继承,因为继承就有可能破坏类的结构。

Final

final类又叫做最终类,指的是使用final 关键字修饰的类,不可以被其他类继承。

final关键字还能修饰方法,表示被修饰的方法不能被子类重写。

final类的意义:不可以继承,防止类结构被破坏

抽象类

有些类不能够被实例化,只能被继承。

抽象类是使用abstract关键字修饰的类。

抽象类只能被继承

abstract关键字可以用在方法上;表示当前方法是抽象方法,抽象方法不能有方法体(大括号)

抽象方法必须被子类实现:重写并添加方法体

实现抽象类的抽象方法

继承抽象方法:子类也必须是抽象类

一个拥有抽象方法的类一定是抽象类(必须显示的对类使用关键字abstract

抽象类的意义:抽象类用于规范下面的子类里面所拥有的方法的名字

如果项目较大,有可能使用抽象类,如果项目很小或者说不需要那么多规范,就不怎么使用抽象类。

抽象类中可以拥有普通类中任何的类成员,但是不能使用私有的访问修饰限定符(private

接口

接口分为很多种

         应用型接口:一种可以允许外部使用的入口

         数据型接口:用来规范外部去实现某些功能的方式(结构规范)

定义接口

语法:interface接口名字{//接口体}

接口体

接口体也称之为接口成员,指的是在接口中可以定义的内容。

在接口中,只能有方法和常量,而且方法必须是抽象(不需要abstract关键字:没有方法体)的,而且只能public修饰。

接口不能被实例化,接口也不能被“继承”,接口只能被实现:implements

实现接口

实现接口值用类去实现接口,必须要实现接口中的所有的抽象方法。

接口意义

与抽象类一样,用来规范底层的类的结构。比抽象类更加严格的规范结构。接口是一种纯粹用于规范的一种结构。

接口只有在团队比较大,分支比较多的情况下,用于规范整个团队,保证内部的不同分支下的结构相同。

接口的特殊使用

接口可以多实现,一个类可以同时实现多个接口

class 类名 implements 接口1,接口2,…{}

接口可以继承接口:interface A extends B{} //B是接口

常见的面试题

1.      抽象类是不是类?

抽象应该理解为是类,但是不能被实例化的类。(用的是关键字class

2  PHP是否支持多继承?如何模拟?

PHP不支持多继承,链式继承去模拟实现。

2.      接口是不是类?接口是不是抽象类?

接口不是类,接口是interface,而类是class;接口也不是抽象类

3.      接口能不能被继承?

接口只能被类实现,但是接口是可以被接口继承的。

类相关常用的方法

class_exists:判断类在内存中是否存在,用于在类的加载之前进行数据判断

interface_exists:判断接口是否存在

method_exists:判断方法是否存在,只要方法存在,跟方法所有的访问修饰限定符没有关系

get_class:得到对象类名

get_parent_class:得到父类名,获取当前对象对应的类的上级类的类名,如果上级也是继承自其它类,则获取不到。(只能获取父类名)

重载

重载:overload,被重新加载。在面向对象里,重载指的当一个函数(方法),具有不同的返回值或者参数列表的时候,可以有不同的存在形式(允许同名函数存在:返回值或者参数列表不一样)

class Person{

         public string function eat(){//吃饭方法;return '吃饱了’;}

         public string function eat(水果){//吃水果;return '好吃’;}

public string function eat(主食){//吃主食;return '好吃’;}

}

PHP中不支持传统意义上的重载,因为php不允许同名函数(方法)存在。

PHP重载

当在PHP去访问一个没有权限或者不存在的属性或者方法的时候,会自动触发相关的魔术方法,这种机制就称之为PHP的重载。

属性重载

可以无限制的为一个对象增加属性。

无限制的增加会破会对象的结构。

魔术方法有很多:

__get():获取的意思,当对象去访问一个不存在或者权限不够的属性的时候,会自动触发的方法

__set():与get一致,是不存在或者权限不够的时候,会自动触发的设置方法。

__isset()issetempty时调用,当在外部使用isset或者empty去判断一个权限不够或者不存在的属性的时候,会自动调用

__unset()unset调用,当外部对对象的属性进行unset处理的时候会自动调用的方法

注意:所有的魔术方法都是为了增加类的容错处理以及对结构的控制(对象)

方法重载

当去访问一个权限不够或者不存在的方法的时候,会自动触发的魔术方法。

__call():普通方法,对象调用

__callStatic():静态方法,类调用

PHP重载意义

1.      为了增加类的容错处理,不会让代码因为访问一些不存在的或者权限不够的属性或者方法的时候,直接报错

2.      为了保护对象的结构:不允许无限增加,不允许随意unset(删除)

需求:允许第一次操作从类实例化对象,但是其后的每次操作都要求将对象保存到文件,然后直接取出来使用。

对象的保存和还原

将对象保存到对应的文件里,然后再取出来使用(取出之后依然是对象)。

文件内部只能存储字符串,而对象是复合数据,不能存放到文件。

对象的保存

想办法将一个对象转换成字符串,转换成一个有结构的字符串。(结构:按照数据类型进行处理的结构)

序列化:将一个复合数据类型,按照里面本身数据(元素或者属性)的数据类型,进行整理,整理成一个可以被还原的带结构的字符串;

serialize:参数是一个复合数据类型,返回值是一个字符串

对象的还原

还原就是将一个有结构的字符串转换成一个对应的数据类型(复合)。

反序列化:将序列化后的字符串还原成原来的结构。

unserialize:参数是一个序列化好的字符串,而返回值是一个对应的数据类型

要保证反序列化能得到对应的类,必须保证对应的类在内存中存在,否则系统会默认的变成系统类的对象。

自动加载

资源类型是不可以被序列化:当对一个数据进行序列化的时候,如果里面有资源类型,会自动的会被转成int类型,并且失去该资源。

魔术方法:专门用于数据对象保存和还原

__sleep():睡眠,当一个对象想要变得不再活跃的时候(写入到文件:序列化),会自动调用的方法,这个方法用于指定保存到文件中所有属性(资源属性没有必要保存)

效果

反序列化效果

希望在反序列化的时候,系统能够自动的与服务器建立连接。

__wakeup():唤醒,当一个休眠状态的对象被重新唤醒(反序列化)会自动调用的魔术方法

效果

自动加载机制

对象遍历

对象中只保存了属性,所谓的对象遍历就是遍历对象中的属性(只能是public属性)。

遍历对象与遍历数组一致,使用foreach

需求:需要遍历对象中某一个指定的属性(属性是一个数组),如果想通过foreach直接遍历对象的话是不可能实现的。

如果要实现,需要修改对象对应类的实现机制,必须去实现一个叫做Iterator的接口。实现对应的方法,来修改foreach在遍历对象时候的机制。

实现接口Iterator

如果数组元素本身出现false或者可以转换成false的元素值,那么就会实现

需要通过判断数组的下标来进行数组指针的有效性判断。

    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多