面向过程:是一种以过程为中心的编程思想;一般是自顶向下解决问题。
面向对象:面向对象是一种对现实世界理解和**抽象**的方法,是计算机编程技术发展到一定阶段后的产物。
PHP中面向对象的抽象以类class体现;每个类的定义都以关键字class开头,后面跟着类名,后面跟着一对花括号,里面包含有类的属性与方法的定义。一个类可以包含有属于自己的常量,变量(称为"属性")以及函数(称为"方法")。
一、OOP中的关键字和含义用法
关键字 | 含义 | 作用 |
---|---|---|
public、protected、private | 用于类属性、方法的访问控制;依次为:公有、受保护、私有 | 类属性和方法为public,类外部可以直接访问或调用;类方法;php4中使用var关键字声明类属性,被认为是public,即var是public的一个别名。私有属性和方法不能被子类继承---但可以通过父类内部的方法处理进行私有变量传递。 |
$this、self、parent、static、const、 ->、:: | 用于类内部属性和方法的调用、定义静态属性或方法以及类常量 |
static用于声明静态属性或方法,就可以不实例化类而直接访问(静态属性无法通过已实例化的对象访问,但静态方法可以(留意访问控制),访问静态属性则需要直接使用类原型【也就是原始类名】以及范围操作符访问,className::$staticVar(依然要留意访问控制) static另外一个功能则是php5.3以后引入的“后期静态绑定”功能,针对继承范围内应用静态调用的类,此时static作为与self、parent相类似的功能,可以使用范围解析操作符::调用。static:: 不再被解析为定义当前方法所在的类(相比于self和parent等静态引用),而是在实际运行时计算。也可以称之为"静态绑定",因为它可以用于(但不限于)静态方法的调用。 伪变量$this和->对象运算符不能用于访问静态方法或属性,而是使用self或对象或类原型以及范围操作符::访问。静态属性不能通过一个类已实例化的对象来访问(但静态方法可以),例如:$obj::staticFunction()---注意此处staticFunction()需为public类型。$this用于类内部访问内部的非静态属性和方法、self用于类内部访问静态属性、静态方法或类常量。const用于定义类常量,5.3以后const也可以在类外部定义,const是一个语言结构,而define是个函数;const定义的常量赋值不得为表达式(php5.6及其以后可以),而define就可以。parent用于继承的子类中调用(并可以重写)父类方法或属性;依然使用范围操作符。 |
abstract |
定义类为抽象类或方法为抽象方法 |
abstract定义抽象类或抽象方法,定义为抽象的类不能被实例化;任何一个类,如果它里面至少有一个方法是被声明为抽象的,那么这个类就必须被声明为抽象的。被定义为抽象的方法只是声明了其调用方式(参数),不能定义其具体的功能实现,即没有花括号的方法体,另外抽象类中的所有抽象方法是子类继承必须实现的,所以定义抽象类中的抽象方法必须能被继承,也就是不能定义为private。继承抽象类的子类中,实现抽象方法的参数数目必须一致(但可以在子类方法中通过可选参数方式规避) |
interface、implements |
指定某个类必须实现哪些方法,但不需要定义这些方法的具体内容(无花括号方法体)。 |
接口可以理解成更抽象化的抽象类;接口(类)是通过interface关键字来定义的,就像定义一个标准的类一样,但其中定义所有的方法都是空的。接口中定义的所有方法都必须是公有,这是接口的特性,当然接口也是无法被new关键词实例化的;接口中的方法可以加public也可不加,但规范化建议加上public关键字声明;接口中的方法可以理解成更抽象的抽象方法,但接口中的方法声明时无需也不能指定abstract关键字(写法一致而已,没有花括号方法体)。实现接口的类必须使用implements关键字,实现接口的类仍然可以是抽象类;接口也可以被继承,也是extends关键字,接口通过extends继承后的依然是接口类,实现继承后的接口依然私用implements关键字。类中必须实现接口中定义的所有方法,否则会报一个致命错误。类可以实现多个接口,用逗号来分隔多个接口的名称,实现多个接口时,多个接口中的方法不能重复(重名)。 接口中可以定义接口常量(与类常量一致,const关键字定义),但是不能被子类或子接口所覆盖。 补充:除了接口以外,合适访问控制的类属性、类方法、类常量、类静态变量均可继承重载。 |
extends、traits、Final |
类继承、代码复用 | extends用于继承,final用于声明类或方法不能被继承或改写,若类被声明为final,则该类无法被继承,若类中的方法被定义为final,则该方法无法被改写(子类可以调用但却无法改写);属性不能被定义为 final,只有类和方法才能被定义为final;traits是为了解决php单继承产生的一种与class类似的代码复用机制或方法,声明一个traits与声明一个class类似,traits可以加强代码复用,另行介绍。 |
namespace、use、use as、__NAMESPACE__、__CLASS__ |
|
namespace命名空间,详见:https://blog.jjonline.cn/phptech/154.html |
clone | 对象克隆 | 大部分时候对象传递,通过字面量引用传递即可 |
二、OOP中的魔术方法和含义用法
魔术方法 | 含义 | 作用 |
---|---|---|
__construct() |
构造函数 |
具有构造函数的类会在每次创建新对象时先调用此方法,所以非常适合在使用对象之前做一些初始化工作。构造函数的重载继承,在子类中需显示的通过parent关键词调用,否则子类中的构造父类中的构造函数并不会潜在的执行。子类中没有构造函数时,此时构造函数与普通方法一样从父类继承(若访问控制运行,即没有被定义为private)。 |
__destruct() |
析构函数 |
析构函数会在到某个对象的所有引用都被删除或者当对象被显式销毁时执行。继承重载之后的特性与构造函数一致。 |
__call() |
对象方法重载 |
在对象中调用一个不可访问方法时,__call() 会被调用。有两个参数,第一个参数为调用的不可访问的方法名,第二个参数是个数组,为调用的不可用方法时传入的参数。 |
__callStatic() |
静态方法重载 |
用对象静态方式或类原型方式调用一个不存在或不可用的静态方式,__callStatic() 会被调用。参数与__call()一致。 |
__get() |
属性重载 |
读取不可访问属性的值时,__get() 会被调用。 一个参数为要被操作的变量(属性)名称 |
__set() |
属性重载 |
在给不可访问属性赋值时,__set() 会被调用。两个参数,第一个参数为操作的变量(属性)名称,第二个参数为变量(属性)值。 |
__isset() |
属性重载 |
当对不可访问属性调用 isset() 或 empty() 时,__isset() 会被调用。一个参数为要被操作的变量(属性)名称 |
__unset() |
属性重载 |
当对不可访问属性调用 unset() 时,__unset() 会被调用。一个参数为要被操作的变量(属性)名称 |
__sleep() |
对象序列化时调用 |
serialize()对象时,该 函数会检查类中是否存在一个魔术方法 __sleep()。如果存在,该方法会先被调用,然后才执行序列化操作。此功能可以用于清理对象,并返回一个包含对象中所有应被序列化的变量名称的数组。如果该方法未返回任何内容,则 NULL 被序列化,并产生一个 E_NOTICE 级别的错误。 |
__wakeup() |
对象反序列化时调用 |
unserialize() 对象序列化后的字符串时,该函数会检查是否存在一个 __wakeup() 方法。如果存在,则会先调用 __wakeup 方法,可以在该函数中预先准备对象需要的资源。 |
__toString() |
对象作为字符串输出时调用 |
__toString() 方法用于一个类被当成字符串时应怎样回应,函数体应该return该类被当做字符串时应该输出的字符串。该函数没有参数。 |
__invoke() |
对象作为函数调用时自动调用 |
当尝试以调用函数的方式调用一个对象时,__invoke() 方法会被自动调用。该函数参数个数不定,依据对象被当做函数调用时传入的参数确定。 |
__set_state() |
|
当对象被var_export()调用导出时,此**静态**方法会被调用。 注意此方法声明时应该显示指明static,静态方法 |
__clone() |
对象复制 | 使用clone关键字复制一个对象后,复制出的对象会立即执行__clone方法,可用于修改复制的对象的属性(若有必要),该方法没有参数。 |
__debugInfo() |
对象调试输出 | 这是php5.6新增的方法,当对象被函数var_dump()函数输出时调用该函数,可以通过该函数控制能被var_dump的属性;该方法没有参数,返回一个数组即可。 |
三、相关代码片段
<?php /** * * @authors Jea杨 * @date 2015-07-17 14:10:58 * @version $Id$ */ interface a { ##类常量(或接口常量)没有访问控制public、protected、private修饰 #public $interfaced; 这句致命错误 因为接口中仅定义方法 不能定义属性 const interfaceConst = "1、这是interface接口a定义的类常量,常量名:abstractConst<br>"; public function __construct();##接口中是可以定义构造函数的 但没有啥意义,因为接口和抽象类均不能被实例化 public function interfaceFunction();#这是接口类定义要被实现的方法 public function interfaceFunction1();#这是接口类定义要被实现的方法 } interface aa { public function interfaceaaFunction(); } abstract class b implements a,aa { #abstract public $abstract = ""; 这句话致命错误 因为类属性不存在抽象属性 #const interfaceConst = "xx"; 这句语句致命错误 因为接口常量不能重写只能继承 public $abstractd = "6、####这是抽象类中定义的类属性####"; private $abstructPrivate = ""; const abstractConst = "2、这是abstract抽象类b定义的常量,常量名:abstractConst<br>"; public function interfaceFunction($a=null) { echo "5、##这是用抽象类实现接口类方法interfaceFunction,请留意参数个数和写法##<br>"; } abstract protected function abstractFunction1(); abstract protected function abstractFunction($a,$b);#这是抽象类定义的要被实现的抽象方法 abstract public function interfaceFunction1();#这是接口类定义要被实现的方法 继承到抽象类的抽象方法 依然不实现 } class c extends b { const interfaceConst = "3、这是子类继承并重载interface接口a中的类常量<br>"; const abstractConst = "4、这是子类继承并重载abstract抽象类b定义的常量<br>"; public function __construct() { #parent::__construct(); echo parent::interfaceConst; echo parent::abstractConst; echo self::interfaceConst; echo self::abstractConst; } /**接口中的所有方法和抽象类中的所有抽象方法在子类中必须都实现***/ public function abstractFunction($a,$b=null,$c=null) { echo "6、###这是用抽象类定义的抽象方法abstractFunction被实现,请留意参数个数和写法###<br>"; } public function abstractFunction1() {} #空方法体就算是实现了抽象方法 但没啥意义 public function interfaceFunction1() {} public function interfaceaaFunction() {} ##接口aa中定义的方法 } ####实例化类c 并调用c中的相关方法 $obj = new c();#构造函数自动运行输出类常量 $obj->interfaceFunction(1); $obj->abstractFunction(1,null,1); #echo $obj->abstructPrivate; 将会有个notice 因为私有属性不会继承 #倘若clas c中定义了一个public的abstructPrivate的属性变量,其与b中的abstructPrivate启示没有任何关系 trait e { static $traits = ""; public function __construct() {echo "1.trait class construct function<br>";} static function show() {echo "2.static function show<br>";} final public function follow() {echo "3.final function<br>";} } class f { use e; } $traitF = new f(); $traitF::show(); $traitF->follow(); /*======================================= 总结知识点: 1、接口中不能定义属性,只能是方法,且全部是public类型 2、接口中的类常量可以被继承,但不无重载(改写)----其他的则均可以 3、用抽象类implements(实现)接口时,抽象类中不实现接口中的方法的情况下该接口中的方法将自动转换为抽象类的抽象方法 =======================================*/
上述代码片段在php5.4执行后的结果为:
1、这是interface接口a定义的类常量,常量名:abstractConst 2、这是abstract抽象类b定义的常量,常量名:abstractConst 3、这是子类继承并重载interface接口a中的类常量 4、这是子类继承并重载abstract抽象类b定义的常量 5、##这是用抽象类实现接口类方法interfaceFunction,请留意参数个数和写法## 6、###这是用抽象类定义的抽象方法abstractFunction被实现,请留意参数个数和写法### 1.trait class construct function 2.static function show 3.final function
当阳,我也是当阳的。Up主70后还是80后还是85后啊?