【学习笔记】PHP面向对面思想 二
四、接口
1.接口的作用:定义一套规范,接口定义的方法在程序中必须全部实现。
2.PHP中的接口和其他语言的区别
在PHP中,只关心是否实现了接口的方法,但是不会关心接口语义是否正确,可以实现接口里不存在的方法。
但是Java中认为接口就是一种类型,除了要实现接口的方法,也不允许调用接口中不存在的方法。
3.对PHP接口的思考
PHP接口相对于Java/C++,在“面向契约编程”中是不足的。在PHP中,接口更像一个设计文档。一般情况下,由于PHP时弱类型语言并强调灵活,并不推荐大规模使用接口,仅在部分内核代码中使用,可以更多地考虑使用抽象类。
五、反射
根据到达地找到出发地和来源,如通过一个对象知道所属类和所拥有的方法。
1.使用反射API
class person{ public $name; public $gender; public function say(){ echo $this->name." is ".$this->gender; } } $student = new person(); //获取对象属性列表 $reflict = new ReflectionObject($student); $props = $reflict->getProperties(); //print_r($props); foreach ($props as $prop){ print $prop->getName()."\n"; } //获取对象方法列表 $method = $reflict->getMethods(); //print_r($method); foreach ($method as $prop){ print $prop->getName()."\n"; }
其中,直接打印props显示:Array ( [0] => ReflectionProperty Object ( [name] => name [class] => person ) [1] => ReflectionProperty Object ( [name] => gender [class] => person ) )
直接打印method显示:Array ( [0] => ReflectionMethod Object ( [name] => say [class] => person ) )
2.反射的作用
可以用于文档生成。对文件的类进行扫描,逐个生成描述文档。
六、异常和错误
1.如何使用异常处理机制
PHP中的异常和错误:异常——逻辑和业务流程的一种中断,是业务逻辑上出现的不合预期、与正常流程不同的状况,并不是语法错误;错误——通常为遇到非正常代码。
PHP只有手动抛出异常后才能捕获异常。
以除零为例
$a = 0; try { if($a == 0){ throw new Exception('除数不能为0', 1); } echo 4/$a;//不会执行 } catch (Exception $e){ echo $e->getMessage(); }
1)基本语法
try{ //可能出现错误或异常的代码 //catch表示捕获,Exception是php已定义好的异常类 } catch(Exception $e){ //对异常处理,方法: //1、自己处理 //2、不处理,将其再次抛出 }
2)异常处理类
//自定义的异常类,继承了PHP的异常基类Exception class MyException extends Exception { function getInfo() { return '自定义错误信息'; } }
try { //使用异常的函数应该位于 "try" 代码块内。如果没有触发异常,则代码将照常继续执行。但是如果异常被触发,会抛出一个异常。 throw new MyException('error');//这里规定如何触发异常。注意:每一个 "throw" 必须对应至少一个 "catch",当然可以对应多个"catch" } catch(Exception $e) {//"catch" 代码块会捕获异常,并创建一个包含异常信息的对象 echo $e->getInfo();//获取自定义的异常信息 echo $e->getMessage();//获取继承自基类的getMessage信息 }
2.PHP的错误级别
1)deprecate(不推荐不建议),表示不影响PHP正常流程,但建议修正
2)notice,语法中存在不当的地方,也不影响PHP正常流程
3)warning,级别较高的错误,语法中有很不恰当的情况
4)fetal error(致命错误),直接导致PHP流程终止,后面代码不再执行
5)parse error(语法解析错误),为语法检查阶段的错误
七、面向对象设计原则
1.单一职责原则(SRP):避免相同的职责分散到不同类中,避免一个类承担太多职责。
【为什么要遵守SRP】1) 可以减少类之间的耦合 2) 提高类的复用性
2.接口隔离原则(ISP):客户端不被迫实现一些用不到的接口,即使用多个专门接口比使用单个接口好
·存在污染的设计
·减少接口的污染
3.开放-封闭原则(OCP)
要求开发人员在不修改系统现有功能代码前提下,实现对应用系统的软件功能拓展,即一个模块在扩展性方面应该是开放的,而在更改性方面应该是封闭的。
4.替换原则(LSP)
子类型必须能够替换掉它们的父类型,并出现在父类能够出现的任何地方。
【问题由来】有一功能P1,由类A完成。现需要将功能P1进行扩展,扩展后的功能为P,其中P由原有功能P1与新功能P2组成。新功能P由类A的子类B来完成,则子类B在完成新功能P2的同时,有可能会导致原有功能P1发生故障。
【解决方案】当使用继承时,遵循里氏替换原则。类B继承类A时,除添加新的方法完成新增功能P2外,尽量不要重写父类A的方法,也尽量不要重载父类A的方法。
5.依赖倒置原则(DIP)
上层模块不能依赖于下层模块,抽象不能依赖于具体。
【问题由来】类A直接依赖类B,假如要将类A改为依赖类C,则必须通过修改类A的代码来达成。这种场景下,类A一般是高层模块,负责复杂的业务逻辑;类B和类C是低层模块,负责基本的原子操作;假如修改类A,会给程序带来不必要的风险。
【解决方案】将类A修改为依赖接口I,类B和类C各自实现接口I,类A通过接口I间接与类B或者类C发生联系,则会大大降低修改类A的几率。