面向对象程序设计,是一种程序设计范型,同时是一种程序开发的方法。它将对象作为程序的基本单元,将程序和数据封装在其中,以提高软件的重用性,灵活性和可扩展性。
面向过程,面向对象和函数式编程,被称为编程语言中的三大范式。
面向对象的核心思想是对象、封装、可重用性和可扩展性。
一个类的设计需要能充分展示其重要的属性和方法,并且能与其他事物相区分。
对于类的理解:
类定义了一系列的属性和方法,并提供了实际的操作细节,这些方法可以用来对属性进行加工。
对象含有类属性的具体值,这就是类的实例化。正是由于属性值的不同,才能区分不同的对象。
类与对象的关系类似一种服务与被服务,加工与被加工的关系,具体而言,就如同原材料和流水线的关系,只要在对象上调用类所存在的方法,就可以对类的属性进行加工,展示其功能
php的对象是由数组来模拟 的
类是由属性和方法组成的,对象则是属性的集合,由同一个类生成的不同对象,拥有各自的不同的属性,但共享了类代码空中方法区域的代码
php 底层的变量类型是zvalue_value
在php5中,对象在底层的实现是采用“属性数组+方法数组”来实现的。
对象在php 中是使用一种zend_object_value结构体来存储的
对象和数组的区别:对象还有一个指针,它指向了它所属的类
对象与类的关系:
- 类是定义一系列属性和操作的模板,而对象则把属性进行具体化,然后交给类处理
- 对象就是数据,对象本身不包含方法,但是对象有一个指针指向一个类,这个类里可以有方法
- 方法描述了不同属性所导致的不同表现
- 类和对象是不可分割的,有对象就必定有一个类和其对应,否则这个对象就成了没有亲人的孩子(但有一个特殊的情况,就是由标量进行强制类型转换的对象,没有一个类和它对应。此时php中一个称为“孤儿”的stdClass类就会收留这个对象)
php的重载:动态的创建类的属性和方法
get_class (): 获取当前调用方法的类名;
get_called_class():获取静态绑定后的类名;
php 魔术方法:
__construct() 构造方法,该方法在类被实例化成对象的时候调用(也就是在每次创建对象的时候被调用)
__destruct() 析构方法 ,该方法会在对象的所有引用被删除,或者对象被显示销毁的时候被调用
__set($name,$value),给不可访问的属性赋值时,该方法会被调用
__get($name) ,读取不可访问的属性时,该方法会被调用
__isset($name
),当对不可访问的属性调用isset()或empty()时,该方法会被调用
__unset($name),当对不可访问的属性调用unset()方法时,该方法会被 调用
__call($name,$arguments) 当调用对象中不存在的方法时,该方法会被调用 ,$name 是方法名 ,$arguments是传递给方法的参数,是个数组
__callStatic($name,$arguments),当调用对象中不存在的静态方法时,该方法会被调用
__toString(),当一个对象被当作字符串对待的时候,会触发这个魔术方法
继承
类与类之间有一种父子关系,子类继承了父类的属性和方法,称为继承
调用父类构造函数 parent::__construct()
在继承中,parent指父类,self指自身
如果申明类成员或方法为static,就可以不实例化类而直接访问,同时也不能通过一个对象访问其中的静态成员(静态方法除外),也不能用“::“访问一个非静态方法。
耦合
耦合是一个软件结构内不同模块之间互连程度的度量,也就是不同模块之间的依赖关系。
低耦合是指模块之间,尽可能独立存在,模块与模块之间的接口尽可能少而简单。
解耦
解耦是接触模块与模块之间的耦合
如何使用继承?
1.精心设计专门用于被继承的类,继承树的抽象层应该比较稳定,一般不要多余三层
2.对于不是专门用于被继承的类,禁止其被继承,就是使用final修饰符。使用final修饰符既可防止重要方法被覆写,又能给编辑器寻找优化的机会
3.有限考虑用组合关系提高代码的重用性
4.子类是一种特殊的类型,而不只是父类的一个角色
5.子类扩展,而不是覆盖或使父类的功能失效
6.底层代码多用组合,顶层/业务代码多用继承,底层用组合可以提高代码效率,避免对象臃肿。顶层代码用继承可以提高灵活性,让业务使用更方便。
多态
同一个类的对象收到相同的消息时,会得到不同的结果,多态顾明思议,就是多种状态,也就是多种结果
多态性是一种通过多种状态或阶段描述相同对象的编程方式。它的真正意义在于:实际开发中,只要关系一个接口或基态的编程。而不必关心一个对象所属的具体类。
接口
接口常用来作为类与类之间的一个"协议"。接口是抽象类的变体,接口中的所有方法都是抽象的,没有一个有程序体,接口为抽象而生。在程序里,接口的方法必须被全部实现,否则将报fetal错误
traits 是可以导入包含代码的接口
关于接口的总结
- 接口作为一个规范和契约存在。作为规范,接口应该保证可用性;作为契约,接口应该保证可控性。
- 接口只是一个声明,一旦使用interface关键字,就应该实现它。可以有程序员实现(外部接口),也可以由系统实现(内部接口)。接口本身什么也不做,但是它可以告诉我们它能做什么
- PHP接口存在2个不足,一是没有契约限制,二是缺少足够多的内部接口
反射
面向对象编程中对象呗赋予了自省的能力,而这个自省的过程就是反射
反射指在PHP运行状态中,扩展分析PHP程序,导出或提取出关于类、方法、属性、参数等的详细 信息,包括注释。这种动态获取信息以及动态调用对象方法的功能称为反射API.
获取对象属性列表:创建一个反射对象,调用该对象的getProperties()方法
获取对象的方法列表:创建一个反射对象,调用该对象的getMethods()方法
例子:
//获取对象属性列表,$student要反射的对象 $reflect = new ReflectionObject($student)//创建反射对象 $props = $reflect->getProperties(); foreach($props as $prop){ print $prop->getName()." "; } //获取对象方法列表 $m = $reflect->getMethods(); foreach($m as $prop){ print $prop->getName()." "; }
以上是使用了反射API,其实也可以使用class函数,返回对象属性的关联数组以及更多信息:
//返回对象属性的关联数组 var_dump(get_object_vars($students)); //类属性 var_dump(get_class_vars(get_class($student))); //返回由类的方法名组成的数组 var_dump(get_class_methods(get_class($student)));
放射API的功能很强大,甚至可以还原这个类的原型,包括方法的访问权限,如代码清单
$obj = new ReflectionClass('person') $className = $obj->getName(); $Methods = $Properties = array(); foreach($obj->getProperties() as $v){ $Properties[$v->getName()]=$v; } foreach($obj->getMethods() as $v){ $Methods[$v->getName()]= $v; } echo "class {$className} { "; is_array($Properties)&&ksort($Properties); foreach($Properties as $k=>$v){ echo " "; echo $v->isPublic()?' public':'',$v->isPrivate()?' private':'' , $v->isProtected()?' protected':'' , $v->isStatic()?' static':''; echo " {$k} "; } echo " "; if(is_array($Methods)) ksort($Methods); foreach($Methods as $k=>$v){ echo " function{$k}(){} "; } echo "} ";
php 手册中,关于反射的API高达几十个,可以说放射完整地描述了一个类或者对象的原型。反射不仅用于类和对象,还可以用于函数、扩展模块、异常等。
反射用途
放射可以用来生成文档
php 只有手动抛出异常后才能捕获异常
php错误:使脚本运行不正常的情况
php错误分类:
- deprecated是最低级别的错误,表示‘不推荐,不建议’,它不影响php的正常流程,但一般情况建议修正
- notice 这种一般告诉你语法中存在不当的地方,这种错误不影响PHP正常流程
- warning是级别比较高的错误,在语法中出现很不恰当的情况才会报此级别的错误,比如函数参数不匹配,这种级别的错误会导致得不到预期结果,故需修改代码
- 更高级别的错误是fetal error。这是致命错误,直接导致PHP流程终结,后面的代码不在执行。这种问题非改不可
- 最高级别的错误是语法解析错误prase error,上面的错误都属于PHP代码运行期间错误,而语法解析错误属于语法检查阶段错误,这将导致PHP代码无法通过语法检查
php的错误级别不止以上5种,以上是最常用的,php一共制定了16的错误级别
屏蔽错误的方法:
- 使用error_reporting(0)
- 在函数前面加@,如:@mysql_connect()
使用自定义的错误处理函数
set_error_handler(error_function,error_type);
error_function :规定发生错误时运行的函数,必须
error_type:规定在哪个错误报告级别会显示用户定义的错误。可选,默认为“E_ALL”.
自定的错误处理函数,一定要有这四个输入变量 $error,$errstr,$errfile,$errline
function customError($error,$errstr,$errfile,$errline){ echo "<b>错误代码:</b>[${error}]${errstr} "; echo "错误所在的代码行:{$errline} 文件{$errfile} "; echo "PHP版本",PHP_VERSION,"(",PHP_OS,") "; } set_error_handler("customError",E_ALL|E_STRICT); $a = array('0'=>2,4,6,8); echo $a[0];
restore_error_handler() 取消错误接管
function show_error($error,$errorstr,$errfile,$errline){ // echo "<b>错误代码</b>[$error] [$errorstr]<br/>"; //echo "错误处理所在行:{$errline} 文件{$errfile}<br/>"; //echo "PHP版本",PHP_VERSION,"(",PHP_OS,")<br/>"; throw new Exception("<b>错误代码</b>[$error] [$errorstr]<br/>错误处理所在行:{$errline} 文件{$errfile}<br/>PHP版本,".PHP_VERSION.",(".PHP_OS.")<br/>"); } set_error_handler('show_error',E_ALL|E_STRICT); restore_error_handler();//恢复系统错误处理函数 try{ $a = 5/0; }catch(Exception $e){ echo '',$e->getMessage(); }
结果:
Warning: Division by zero in D:phpStudyPHPTutorialWWW est est.php on line 52