1.4 面向对象摘要

面向对象包括3部分内容:OOA、OOD、OOP。面向对象编程的两个重要概念是类和对象。

面向对象编程的三大特点

封装、继承、多态。

封装性

封装性,也可以称为信息隐藏。就是将一个类的使用和实现分开,只保留有限的接口(方法)与外部联系。这样对于用到该类的开发人员,只要知道这个类如何使用即可,而不用去关心这个类是如何实现的。

  • public

  • private

  • protected

继承性

继承性就是派生类(子类)自动继承一个或多个基类(父类)中的属性与方法,并可以重写或添加新的属性或方法。继承这个特性简化了对象和类的创建,提高了代码的可重用性。继承分单继承和多继承,PHP 所支持的是单继承,也就是说,一个子类有且只有一个父类。

继承简化了对象、类的创建,增加了代码的可重用性。但PHP只支持单继承。如果想实现多重继承,就要使用接口或者 Trait。

接口实例:

<?php
interface 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 实例

<?php
trait 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代码实现多态:

<?php
abstract 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 加密函数

Last updated