面向对象思想的核心概念

目录对象与数组对象与类魔术方法的应用继承与多态各种语言中的多态面向接口编程反射异常和错误处理PHP中的错误级别PHP中错误处理机制 面向对象程序设计(Obje

面向对象程序设计(Object Oriented Programming,OOP)是一种程序设计范式,同时也是一种程序开发方法。它将对象作为程序的基本单元,将程序和数据封装其中,以提高软件的重用性、灵活性和扩展性。

面向过程、面向对象以及函数式编程被人们称为编程语言中的三大范式(实际上,面向过程和面向对象都同属于命令式编程),是三种不同编码和设计风格。其中面向对象的核心思想是对象、封装、可重用性和可扩展性

类是对象的抽象组织,对象是类的具体存在。

类是我们对一组对象的描述,类定义了一系列的属性和方法,并提供了实际的操作细节,这些方法可以用来对属性进行加工。

对象含有类属性的具体值,这就是类的实例化。
类与对象的关系类似一种服务被服务、加工与被加工的关系。

类是属性和方法的集合,那么在PHP中,对象是什么呢?比较普遍的说法就是“对象由属性和方法组成”。

对象与数组

对象是什么,我们不好理解,也不容易回答,但是我们知道数组是什么。数组的概念比较简单。数组是由键值对数组组成的,数组的键值对和对象的属性/属性值对十分相似。对象序列化后和数组序列化后的结果是惊人的相似。
而对象和数组的区别在于:对象还有个指针,指向了它所属的类。

对象与类

类是定义了一系列属性和操作的模板,而对象则把属性进行具体化,然后交给类处理。
对象就是数据,对象本身不包括方法。但对象有一个"指针"指向一个类,这个类里可以有方法。

方法描述不同属性所导致的不同表现。

类和对象是不可分割的,有对象就必定有一个类和其对应,否则这个对象也就成了没有亲人的孩子。(但有一个特殊情况存在,就是由标量进行强制类型转换的object,没有一个类和它对应。此时,PHP中一个被称为“孤儿”的stdClass类就会收留这个对象)

魔术方法的应用

魔术方法是以两个下划线“”开头具有特殊作用的一些方法,可以看做PHP的“语法糖”。

语法糖指那些没有给计算机语言添加新功能,而只是对人类来说更“甜蜜”的语法。语法糖往往给程序员提供了更实用的编码方式或者一些技巧性的用法,有益于更好的编码风格,使代码更易读。不过其并没有给语言添加什么新东西。PHP里的引用、SPL等都属于语法糖。

<?php
class person{
    // 构造方法
    // 每次创建对象时先调用此方法,适合在使用对象之前做一些初始化工作。如给属性赋值、连接数据库等
    public function __construct()
    {
        
    }
    
    // PHP提供的“重载”指动态地“创建”类属性和方法。set和get方法都被归到重载里。
    // 当给对象属性赋值或者取值时,即使这个属性不存在,也不会报错,一定程度上增强了程序的健壮性。
    public function __set()
    {
        
    }
    public function __get()
    {
        
    }
    
    // 如何防止调用不存在的方法而出错?一样的道理,使用call魔术重载方法。
    // call方法原型如下:
    // mixed call (string $name, array $arguments)
    // 当调用一个不可访问的方法(如未定义,或者不可见)时,call()会被调用。
    // 其中name参数是要调用的方法名称。arguments参数是一个数组,包含着要传递给方法的参数。
    public function call($name, $arguments)    
    {
        
    }
    // 当echo输出对象时,会自动调用toString方法,否则会报错
    public function toString()
    {
        
    }
    // 当调用一个不可访问的静态方法时,callStatic()会被调用。
    public function callStatics()
    {
        
    }
    
    // 析构方法
    // 析构方法会在某个对象的所有引用被删除或者当对象被显式销毁时执行
    public function __destruct()
    {
        
    }
}

继承与多态

面向对象的优势在于类的复用。
把一个类的对象当作另一个类的属性,并调用它的方法处理问题,这种复用方式叫“组合”。
类与类之间有一种父与子的关系,子类继承父类的属性和方法,称为继承。

从方法复用角度考虑,如果两个类具有很多相同的代码和方法,可以从这两个类中抽象出一个父类,提供公共方法,然后两个类作为子类,提供个选哪个方法。这时用继承语意更好。

在继承中,用parent指代父类,用self指代自身。使用“:”运算符(范围解析操作符)调用父类的方法。“:”操作符还用来作为类常量和静态方法的调用。如果声明类成员或方法为static,就可以不实例化类而直接访问,同时也就不能通过一个对象访问其中的静态成员,也不能使用“:”访问一个非静态方法。

而组合就没有那么多限制。组合之间的类可以关系(体现为复用代码)很小,甚至没有关系。

在编程中,继承与组合的取舍往往并不是这么直接明了,很难说出两者是“像”的关系还是“需要”的关系,甚至把它拿到现实世界中建模,还是无法决定应该是继承还是组合。那应该怎么办呢?有什么标准吗?有的。这个标准就是“低耦合”。

耦合是一个软件结构内不同模块之间互连程度的度量,也就是不同模块之间的依赖关系。
低耦合指模块与模块之间,尽可能地使模块间独立存在;模块与模块之间的接口尽量少而简单。现代的面向对象的思想不强调为真实世界建模,变得更加理性化一些,把目标放在解耦上。

解耦是要解除模块与模块之间的依赖。

继承与组合二者语义上难于区分,在两者均可使用的情况下,更倾向于使用组合。为什么呢?继承存在什么问题呢?

  1. 继承破坏封装性。
    比如,定义鸟类为父类,具有羽毛属性和飞翔方法,其子类天鹅、鸭子、鸵鸟等继承鸟这个类。显然,鸭子和鸵鸟不需要飞翔这个方法,但作为这个子类,它们去可以无区别地使用飞翔这个方法,显然破坏了类的封装性。而组合,从语义上来说,要优于继承。

  2. 继承是紧耦合的
    继承使得子类和父类捆绑在一起。组合仅通过唯一接口和外部进行通信,耦合度低于继承。

  3. 继承扩展更复杂
    随着继承层的增加和子类的增加,将涉及大量方法重写。使用组合,可以根据类型约束,实现动态组合,减少代码。

  4. 不恰当地使用继承可能违反现实世界中的逻辑
    比如,人作为父类,雇员、经理、学生作为子类,可能存在这样的问题,经理一定是雇员,学生也可能是雇员,而使用继承的话一个人就无法拥有多个角色。这种问题归结起来就是“角色”和“权限”问题。在权限系统中很可能存在这样的问题,经理没有权限直接操作主管所负责的资源,技术部经理也没权限直接命令市场部主管。这就要求角色和权限系统的设计要更灵活。不恰当地继承可能导致逻辑混乱,而使用组合就可以较好地解决这个问题。
    当然,组合并非没有缺点。在创建组合对象时,组合需要——创建局部对象,这一定程度上增加了一些代码,而继承则不需要这一步,因为子类自动有了父类的方法。组合还有其他的一些缺点,不过总体来说,是优点大于缺点。

继承最大的优点是扩展简单,但是其缺点大于优点,所以在设计时,需要慎重考虑。那应该如何使用继承呢?

精心设计专门用于被继承的类,继承树的抽象层应该比较稳定,一般不要多于三层。

对于不是专门用于被继承的类,禁止其被继承,也就是使用final修饰符。使用final修饰符既可防止重方法被非法重写,又给能编辑器寻找优化的机会。

优先考虑组合关系提高代码的可重用性。

子类是一种特殊的类型,而不只是父类的一个角色。

子类扩展,而不是覆盖或者使父类的功能失效。

底层代码多用组合,顶层/业务代码代码多用继承。底层用组合可以提高效率,避免对象臃肿。顶层代码用继承可以提高灵活性,让业务使用更方便。

继承并非一无是处,而组合也不是完美无缺。如果既要组合的灵活,又要继承的代码简洁,能做到吗?

这是可以做到的,譬如多重继承,就具有这个特性。多重继承里一个类可以同时继承多个父类,组合两个父类的功能。C++里就是使用的这种模型来增强继承的灵活性的,但是多重继承过于灵活,并且会带来“菱形问题”,故为其使用带来了不少困难,模型变得复杂起来,因此在大多数语言中,都放弃了多重继承这一模型。

多重继承太复杂,PHP5.4引入的新的语法结构Traits就是一种很好的解决方案,可以很方便实现对象的扩展,是除extend、implements外的另外一种扩展对象的方式。Traits既可以使单继承模式的语言获得多重继承的灵活,又可以避免多重继承带来的种种问题。

各种语言中的多态

多态确切的含义是:同一类的对象收到相同消息时,会得到不同的结果。而这个消息是不可预测的。多态,顾名思义,就是多种状态,也就是多种结果。

多态性是一种通过多种状态或阶段描述相同对象的编程方式。它的真正意义在于:实际开发中,只要关心一个接口或基类的编程,而不必关心一个对象所属于的具体类。

PHP作为一门脚本语言,自身就是多态的。

通过判断传入的对象所属的类不同来调用其同名方法,得出不同结果,这是多态吗?如果站在C++角度,这不是多态,这只是不同类对象的不同表现而已。C++里的多态指运行时对象的具体化,指同一类对象调用相同的方法而返回不同的结果。

区别是否是多态的关键在于看对象是否属于同一类型。如果把它们看做同一种类型,调用相同的函数,返回了不同的结果,那么它就是多态;否则,不能称其为多态。由此可见,弱类型的PHP里多态和传统强类型语言里的多态在实现和概念上是有一些区别的,而且弱类型语言实现起多态来会更简单,更灵活。

总结如下:

多态指同一类对象在运行时的具体化。

PHP语言是弱类型的,实现多态更简单、更灵活。

类型转换不是多态。

PHP中父类和子类看做“继父”和“继子”关系,它们存在继承关系,但不存在血缘关系。因此子类无法向上转型为父类,从而失去多态最典型的特征。

多态的本质就是 if ……else,只不过实现的层级不同。

面向接口编程

面向接口编程并不是一种新的编程范式。其次,这里指的是狭义的接口,即interface关键字。广义的接口可以是任何一个对外提供服务的出口,比如提供数据传输的USB接口、淘宝网对其他网站开发的支付宝接口。

接口定义一套规范,描述一个“物”的功能,要求如果现实中的“物”想成为可用,就必须实现这些基本功能。接口这样描述自己:

“对于实现我的所有类,看起来都应该像我现在这个样子。”

采用一个特定接口的所有代码都知道对于那个接口会调用什么方法。这便是接口的全部含义。接口常用来作为类与类之间的一个“协议”。接口是抽象类的变体,接口中所有方法都是抽象的,没有一个有程序体。接口除了可以包含方法外,还能包含常量。

接口起了一个强制规范和契约的作用。

接口不仅规范接口的实现者,还规范接口的执行者,不允许调用接口中本不存在的方法。当然这并不是说一个类如果实现了接口,就只能实现接口中才用的方法,而是说,如果针对的是接口,而不是具体的类,则只能按接口的约定办事。这样的语法规定对接口的使用是有利的,让程序更加健全。根据这个角度讲,为了保证接口的定义,通常一个接口的实现类仅实现该接口所具有的方法,做到专一,当然这也不是一成不变的。

通常在大型项目中,会把代码进行分层和分工。核心开发人员和技术经理编写的流程和代码,往往是以接口的形式给出,而基础开发人员则针对这些接口,填充代码。这样,核心技术人员把更多精力投入到了技术攻关和业务逻辑中。前端针对接口编程,只管在Action层调用Service,不管实现细节;而后端则要负责Dao和Service层接口实现。这样,就实现了代码分工与合作。

由于PHP是弱类型,且强调灵活,所以并不推荐大规模使用接口,而是仅在部分“内核”代码中使用接口,因为PHP中的接口已经失去很多接口应该具有的语义。从语义上考虑, 可以更多地使用抽象类。

反射

面向对象编程中对象被赋予了自省的能力,而这个自省的过程就是反射。

反射指在PHP运行状态中,扩展分析PHP程序,导出或提取关于类、方法、属性、参数等的详细信息,包括注释。这种动态获取信息以及动态调用对象方法的功能称为反射API。

反射API 的功能很强大,甚至能还原这个类的原型,包括方法的访问权限。反射完整地描述了一个类或者对象的原型。反射不仅可以用于类和对象,还可以用于函数、扩展模块、异常等。

反射可以用于文档生成。因此可以用它对文件里的类进行扫描,逐个生成描述文档。

反射可以做动态代理,来代替实际的类运行,并且在方法运行前后进行拦截,动态地改变类中的方法和属性。

在平常开发中,用到反射的地方不多:一个是对对象进行调试,另一个是获取类的信息。在MVC和插件开发中,使用反射很常见,但是反射的消耗也很大,在可以找到替代方案的情况下,不要滥用。

很多时候,善用反射能保持代码的优雅和简洁,但反射也会破坏类的封装性,因为反射可以使本不应该暴露的方法或属性被强制暴露了出来,这既是优点也是缺点。

异常和错误处理

在语言级别上,通常具有许多错误处理模式,但这些模式往往建立在约定俗成的基础上,也就是说这些错误都是预知的。但是在大型程序中,如果没出调用都去逐一检查错误,会让代码变得冗长复杂,到处充斥着if……else,并且严重降低代码的可读性。而且人的因素也是不可信赖的,程序员可能并不会把这些问题当一回事,从而导致业务异常。在这种背景下,就逐渐形成了异常处理机制。

异常的思想最早可以追溯到20世纪60年代,其在C++Java中发扬光大,PHP则部分借鉴了这两种语言的异常处理机制。

PHP里的异常,是程序运行中不符合预期的情况及与正常流程不同的状况。一种不正常的情况,就是按照正常逻辑不该出错,但仍然出错的情况,这属于逻辑和业务流程的一种中断,而不是语法错误。PHP里的错误则属于自身问题,是一种非法语法或者环境问题导致的、让编译器无法通过检查甚至无法运行的情况。

在各种语言中,异常(exception)和错误(error)的概念是不一样的。在PHP里,遇到任何自身错误都会触发一个错误,而不是抛出异常(对于一些情况,会同时抛出异常和错误)。PHP一旦遇到非正常代码,通常都会触发错误,而不是抛出异常。在这个意义上,如果想使用异常处理不可预料的问题,是办不到的。比如,想在文件不存在且数据库连接打不开时触发异常,是不可行的。这在PHP里把它作为错误抛出,而不会作为异常自动捕获。

那PHP里的异常应该怎么用?在什么时候抛出异常,什么时候捕获呢?什么场景下能应用异常?在下面三个场景下会用到异常处理机制。

1.对程序的悲观预测

如果一个程序员对自己的代码有“悲观情绪”,这里并不是指该程序员代码质量不高,而是他认为自己的代码无法一一处理各种可预见、不可预见的情况,那该程序员就会进行异常处理。假设一个场景,程序员悲观地认为自己的这段代码在高并发条件下可能产生死锁,那么他就会悲观地抛出异常,然后在死锁时进行捕获,对异常进行细致的处理。

2.程序的需要和对业务的关注

如果程序员希望业务代码中不会充斥大堆的打印、调试等处理,通常他们会使用异常机制;或者业务上需要定义一些自己的异常,这个时候就需要自定义一个异常,对现实世界中各种各样的业务进行补充。比如上班迟到,这种情况认为是一个异常,要收集起来,到月底集中处理,扣你工资;如果程序员希望有预见性地处理可能发生的、会影响正常业务的代码,那么它需要异常。在这里,强调了异常是业务处理中必不可少的环节,不能对异常视而不见。异常机制认为,数据一致很重要,在数据一致性可能被破坏时,就需要异常机制进行事后补救。

举个例子,比如有个上传文件的业务需求,要把上传的文件保存在一个目录中,并在数据库里插入这个文件的记录,那么这两步就是互相关联、密不可分的一个集成的业务,缺一不可。文件保存失败,而插入纪录成功就会导致无法下载文件;而文件保存成功数据库写入失败,则会导致没有记录的文件成为死文件,永远得不到下载。

那么假设文件保存成功后没有提示,但是保存失败会自动抛出异常,访问数据库也一样,插入成功没有提示,失败则自动抛出异常,就可以把这两个有可能抛出异常的代码段包在一个try语句里,然后用catch捕获错误,在catch代码段里删除没有被记录到文件或者删除没有文件的记录,以保证业务数据的一致性。因此,从业务这个角度讲,异常偏重于保护业务数据一致性,并且强调对异常业务的处理。

如果代码中只是象征性地try……catch,然后打印一个报错,最后over。这样的异常不如不用,因为没有体现异常思想。

<?php
try {
    // 可能出错的代码段
    if(文件上传不成功) throw (上传异常);
    if(插入数据库不成功) throw (数据库操作异常);
} catch (异常) {
    必须的补救措施,如删除文件、删除数据库插入记录,这个处理很细致
}
// ……

也可以如下

<?php
上传 {
    if(文件上传不成功) throw (上传异常);
    if(插入数据库不成功) throw (数据库操作异常);
}
// 其他代码……
try {
    上传;其他;
} catch (上传异常) {
    必须的补救措施,如删除文件,删除数据库插入记录
} catch (其他异常) {
    记录log
}

上面两种捕获异常的方式中,前一种是在异常发生时立刻捕获;后一种是分散抛异常集中捕获。那到底应该是吧哪一种呢?

如果业务很重要,那么异常越早处理越好,以保证程序在意外情况下能保持业务处理的一致性。比如一个操作有多个前提步骤,突入按最后一个步骤异常了,那么其他前提操作都要消除掉才行,以保证数据的一致性。并且在这种核心业务下,有大量的代码来做善后工作,进行数据补救,这是一种比较悲观的、而又重要的异常。我们应把异常消灭在局部,避免异常的扩散。

如果异常不是那么重要,并且在单一入口、MVC风格的应用中,为了保持代码流程的统一,则常常采用后一种异常处理方式。这种异常处理方式更多强调业务流程的走向,对善后工作并不是很关心。这是一种次要异常,其将异常集中处理从而使流程更专一。

异常处理机制可以把每一件事当作事务考虑,还可以把异常看成一种内建的恢复系统。如果程序某部分失败,异常将恢复到某个已知稳定的点上,而这个点就是程序的上下文环境,而try块里面的代码就保存catch所要知道的程序上下文信息。因此,如果很看中异常,就应该分散进行try……catch处理。

3.语言级别的健壮性要求

在健壮性这点上,PHP是不足的。以Java为例,Java是一种面向企业级开发的语言,强调健壮性。Java中支持多线程,Java认为,多线程被中断这种情况是彻彻底底的无法预料和避免的。所以Java规定,凡是用了多线程,就必须正视这种情况。你要么抛出,不管它;要么捕获,进行处理。总之,你必须面对InterruptedException异常,不准回避。也就是异常发生后应对重要数据业务进行补救,当然你可以不做,但是你必须意识到,异常有可能发生。

这类异常是强制的。更多异常是非强制的,由程序员决定。Java对异常的分类和约束,保证了Java程序的健壮性。

异常就是无法控制的运行时错误,会导致出错时中断正常逻辑运行,该异常代码后面的逻辑都不能继续运行。那么try……catch处理的好处就是:可以把异常造成逻辑中断破坏降到最小范围内,并且经过补救处理后不影响业务逻辑的完整性;乱抛异常和只抛不捕获,或捕获而不补救,会导致数据混乱。这就是异常处理的一个重要作用,就是通过精确控制运行时的流程,在程序中断时,有预见地用try缩小可能出错的影响范围,及时捕获异常发生并做出相应补救,以使逻辑流程仍然能回到正常轨道上。

PHP中的错误级别

PHP错误就是会使脚本运行不正常的情况。

PHP错误有很多种,包括warning、notice、deprecated、fetal error等。这和一般意义的错误概念有些差别。所以,notice不叫通知,而叫通知级别的错误,warning也不叫警告,而叫警告级别的错误。

错误大致分为以下几类。

deprecated是最低级别的错误,表示“不推荐,不建议”。

其次是notice。这种错误一般告诉你语法中存在不当的地方。虽然PHP是脚本语言,语法要求不严,但仍然建议对变量进行初始化。

warning是级别比较高的错误,在语法中出现很不恰当的情况时才会报此错误。

更高级别的错误是fetal error。这是致命错误,直接导致PHP流程终结,后面的代码不再执行。这种问题非改不可。

最高级别的错误是语法解析错误fetal error。上面提到的错误都属于PHP代码运行期间错误,而语法解析错误属于语法检查阶段错误,这将导致PHP代码无法通过语法检查。错误级别不止这几个,最主要的都在前面提到了。PHP手册中一共定义了16个级别错误,最常用的就这几个。

error_reporting指定错误级别。

error_reporting=E_ALL | E_STRICT
display_errors=On

在代码质量或者环境不可控时(比如数据库连接失败),使用error_reporting(0),这样就能屏蔽错误了,正式部署时可以采取这样的策略,防止错误消息泄露敏感信息。另一个技巧就是在函数前加@符号,抑制错误信息输出,如@mysql_connect()。

PHP中错误处理机制

PHP里有一套错误处理机制,可以使用set_error_handler接管PHP错误处理,也可以使用trigger_error函数主动抛出一个错误。

set_error_handler()函数设置用户自定义的错误处理函数。函数用于创建运行期间的用户自己的错误处理方法。它需要先创建一个错误处理函数,然后设置错误级别,语法如下:

set_error_handler(error_function, error_types)

参数描述如下:
error_function:规定发生错误时运行的函数。必需。
error_types:规定在哪个错误报告级别会显示用户定义的错误。可选。默认为“E_ALL”。

如果使用该函数,会完全绕过标准PHP错误处理程序,如果有必要,用户定义的错误处理程序必须终止(die())脚本。

自定义的异常处理函数

<?php
function customError($errno, $errstr, $errfile, $errline){
    echo "<b>错误代码:</b>[${error}]${errstr}\r\n";
    echo "错误所在的代码行:{$errline}文件{$errfile}\r\n";
    echo "PHP版本",PHP_VERSION,"(",PHP_OS,")\r\n";
    // die();
}
set_error_handler("customError", E_ARR | E_STRICT);
$a = array('o' => 2,3,4,6);
echo $a[o];

在函数里,可以对错误的详情进行格式化输出,也可以做任何要做的事情,比如判断当前环境和权限不同给出不同的错误提示,可使用errer_log函数将错误记入log文件,还可以细化处理,针对error的不同进行对应的处理。

自定义的错误处理函数一定要有这四个输入变量errno、errstr、errfile、errline。

errno是一组常量,代表错误的等级,同时也有一组整数和其对应,但一般使用其字符串表示,这样语义更好一点。比如E_WARNING,其二进制掩码为4,表示警告信息。

接下来,就是将这个函数作为回调参数传递给set_error_handler。这样就能接管PHP原生的错误处理函数了。要注意的是,这种托管方式并不能托管所有种类的错误,如E_ERROR、E_PARSE、E_CORE_ERROR、E_CORE_WARNING、E_COMPILE_ERROR、E_COMPILE_WARNING,以及E_STRICT中的部分。这些错误会以最原始的方式显示,或者不显示。

set_error_handler函数会接管PHP内置的错误处理,你可以在同一个页面使用restore_error_handler(); 取消接管。

如果使用自定义的set_error_handler接管PHP的错误处理,先前代码里的错误抑制@将失效,这种错误也会被显示。

在PHP异常中,异常处理机制是有限的,无法自动抛出异常,必须收到进行,并且内置异常有限。PHP把许多异常看做错误,这样就可以把这些“异常”像错误一样用set_error_handler接管,进而主动抛出异常。代码如下所示:

function customError($errno, $errstr, $errfile, $errline){
    // 自定义错误处理时,手动抛出异常
    throw new Exception($level.'|'.${errstr});
    set_error_handler("customError", E_ALL | E_STRICT);
    try {
        $a = 5/0;
    } catch (Exception $e){
        echo "错误信息:",$e->getMessage();
    }
}

这样就能捕获到异常和非致命的错误,这样可以弥补PHP异常处理机制的部分不足。

这种“群则迂回”的处理方式存在的问题就是:必须依靠程序员自己来掌控对异常的处理,对于异常高发区、敏感区,如果程序员处理不好,就会导致前面所提到的业务数据不一致的问题。其优点在于,可以获得程序运行时的上下文信息,以进行针对性的补救。

fetal error这样的错误虽然捕获不到,也无法在发生此错误后恢复流程处理,但是还是可以使用一些特殊方法对这种错误进行处理的。这需要用到一个函数——register_shutdown_function,此函数会在PHP程序终止或者die时触发一个函数,给PHP来一个短暂的“回光返照”。这种方式只是做点收尾工作,但是PHP流程的终止是必然的。对于Parse error级别的错误,可以增加一个配置日志记录,这样一旦PHP发生了错误,就会被记入log文件,方便以后查询。

log_errors=On
error_log=usr/log/php.log

和exception类似,错误处理也有对应抛出错误的函数,那就是trigger_error函数,如下所示:

<?php
$divisor = 0;
if($divisor == 0){
    trigger_error("Cannot divde by zero",E_USER_ERROR);
}
echo "break";

在PHP中,错误和异常是两个不同的概念,这种设计从根本上导致了PHP的异常和其他语言相异。以Java为例,Java中,异常是错误唯一的报告方式。说到底,两者的区别就是对异常和错误的认识不同而产生的。PHP的异常绝大部分必须通过某种办法手动抛出,才能被捕获到,是一种半自动化的异常处理机制。

无论是错误还是异常,都可以使用handler接管系统已有的处理机制。

您可能有感兴趣的文章
什么是面向对象?

JavaScript面向对象详解

java之面向对象详解

面向对象思想(详解)

谈谈对面向对象的理解