面向对象包括3部分内容:OOA、OOD、OOP。面向对象编程的两个重要概念是类和对象。
封装、继承、多态。
封装性
封装性,也可以称为信息隐藏。就是将一个类的使用和实现分开,只保留有限的接口(方法)与外部联系。这样对于用到该类的开发人员,只要知道这个类如何使用即可,而不用去关心这个类是如何实现的。
public
private
protected
继承性
继承性就是派生类(子类)自动继承一个或多个基类(父类)中的属性与方法,并可以重写或添加新的属性或方法。继承这个特性简化了对象和类的创建,提高了代码的可重用性。继承分单继承和多继承,PHP 所支持的是单继承,也就是说,一个子类有且只有一个父类。
继承简化了对象、类的创建,增加了代码的可重用性。但PHP只支持单继承。如果想实现多重继承,就要使用接口或者 Trait。
接口实例:
<?phpinterface a{public function foo();}interface b{public function bar();}interface c extends a, b{public function baz();}class d implements c{public function foo(){}public function bar(){}public function baz(){}}?>
Trait 实例
<?phptrait ezcReflectionReturnInfo {function getReturnType() { /*1*/ }function getReturnDescription() { /*2*/ }}class ezcReflectionMethod extends ReflectionMethod {use ezcReflectionReturnInfo;/* ... */}class ezcReflectionFunction extends ReflectionFunction {use ezcReflectionReturnInfo;/* ... */}?>
注意:从基类继承的成员会被 trait 插入的成员所覆盖。优先顺序是来自当前类的成员覆盖了 trait 的方法,而 trait 则覆盖了被继承的方法。
多态性
先简单说一下多态,多态的三大特征:
子类继承父类
子类重写父类
父类指向子类
多态实现的前提:必须是类与类之间要有关系,要么继承,要么实现,存在重写(override),其实就是抽象函数或接口。
多态的应用:父类对象的引用指向子类对象,其实本质上就是一个向上转型。
多态的好处:大大提高程序的扩展,增强系统的灵活性,降低模块间的耦合。 具体Java代码实现如下:
abstract class Employee{abstract void continueToWork();}class Sales extends Employee{private void makeSalePlan(){System.out.println("make sale plan");}public void continueToWork(){makeSalePlan();}}class Market extends Employee{private void makeProductPrice(){System.out.println("make product price");}public void continueToWork(){makeProductPrice();}}class Engineer extends Employee{private void makeNewProduct(){System.out.println("make new product");}public void continueToWork(){makeNewProduct();}}
错误的调用示范:
class Demo{public static void main(String[] args){Sales s = new Sales();s.continueToWork();Market m = new Market();m.continueToWork();Engineer e = new Engineer();e.continueToWork();}}
以上的这种调用并不能称为多态,虽然看起来都通过调用continueToWork()来得到结果,但是并不是通过同一接口来实现的,这只是不同类的对象都有相同名称的接口方法。
正确的调用方式:
class Demo{public static void main(String[] args){Work(new Sales());//Employee e = new Sales();Work(new Market());//Employee e = new Market();Work(new Engineer());//Employee e = new Engineer();}public static void Work(Employee e){e.continueToWork();}}
上面通过调用统一的接口Work()来工作,这种调用才是多态。
还可以利用重载来实现伪多态。
class Demo{public static void main(String[] args){Work(new Sales());Work(new Market());Work(new Engineer());}public static void Work(Sales s){s.continueToWork();}public static void Work(Market m){m.continueToWork();}public static void Work(Engineer e){e.continueToWork();}}
为什么我称上面调用是伪多态呢?因为上述的这种方式,细究其实跟第一种错误调用方式是一样的,只不过利用了重载加以封装,使得看起来是通过统一的接口Work()来工作,但其实它并没有让父类对象的引用指向子类对象。
php代码实现多态:
<?phpabstract class Employee{abstract function continueToWork();}class Sales extends Employee{private function makeSalePlan(){echo "make sale plan";}public function continueToWork(){$this->makeSalePlan();}}class Market extends Employee{private function makeProductPrice(){echo "make product price";}public function continueToWork(){$this->makeProductPrice();}}class Engineer extends Employee{private function makeNewProduct(){echo "make new product";}public function continueToWork(){$this->makeNewProduct();}}class Demo{public function Work(Employee $employeeObj){//添加父类类型限制传参类型,使其满足多态第三点要求,父类指向子类$employeeObj->continueToWork();}}//调用$obj = new Demo();$obj->Work(new Sales());$obj->Work(new Market());$obj->Work(new Engineer());?>
$this->和"::"的使用
在对类完成实例化之后可以通过对象名+方法名来调用方法“对象名->方法名”。但在定义类时,根本无法得知对象名称是什么,这时如果想调用本类中的方法,就要用伪变量this->方法名,所以this值可以在类的内部使用。
相比伪变量$this只能在类的内部使用,操作符“::”更为强大。操作符"::"可以在没有声明任何实例的情况下访问类中的成员方法和成员变量。
关键字::变量名/常量名/方法名
parent:可以调用父类中的成员变量、成员方法和常量
self:可以调用当前类中的静态成员和常量
类名:可以调用本类中的变量、常量和方法
静态变量(方法)
关键字::静态成员
self:在类内部调用静态成员时所使用。
静态成员所在的类名,在类外调用类内部的静态成员时所使用。
对象比较
在实际开发中可能需要判断两个对象之间的关系时克隆还是引用,这时可以使用比较运算符“==”和“===”。两个等号“==”是比较两个对象的内容,3个等号“===”是比较对象的引用地址。
对象类型检测
instanceof 操作符可以检测当前对象是属于哪个类。
ObjectName instanceof ClassName
PHP 加密函数