PHP面向对象编程高级
1、OOP(Object-Oriented Programming )概述
面向对象的编程特点:代码更简洁、更易于维护,并且具有更强的可重用性。
软件工程的三个目标:重用性、灵活性、扩展性
面向对象编程三大特性:封装、继承、多态(PHP不支持)
2、封装
封装是从对象抽象成类的过程,其将数据和数据的操作捆绑在一起,形成对外界的隐蔽,同时对外提供可以操作的接口
3、继承
继承是类的细分过程,是代码复用的一大手段
继承的基础:子类(要继承其他类的类,派生类)和父类(被继承的类,基类)之间是一种被包含和包含的关系,类似人类(对应子类)和动物类(对应父类)的关系
继承关键字:extends
class Human{} class Man extends Human{}
继承的效果:父类中大多数属性和方法在子类中可以直接访问
有限继承:子类可以继承父类除私有方法之外的所有成员
在PHP中一个类只能继承一个父类,想继承多个类可以尝试使用链式继承
4、成员重写Override
子类中定义了与父类重名的成员的行为称为重写,重写后,子类直接访问重写后的成员,如果需要访问父类中重写前的成员(只包括静态属性、静态方法、类常量和普通方法),可以在子类中使用parent关键字代表父类进行访问parent::成员名称
重写方法原则:
a.控制权不能高于父类
b.参数个数和数据类型(php7)必须一致,形参名字可以更改
c.私有方法不能被继承,故不受重写规则限制
5、静态成员绑定
利用static代替静态绑定self,使用静态成员的重写,使得在类内部用来代表本身的关键字不是在类编译时固定好,而是当方法被访问是动态地选择来访者所属的类
class Human{ public static $name = 'Human'; public static function getName(){ echo self::$name,':self:<br>'; echo static::$name,':static:<br>'; } } class Man extends Human{ public static $name = 'Man'; } Man::getName(); /* *结果 *Human:self: *Man:static: */
静态延迟绑定只有在继承时才有意义,它是根据调用类的不同而选择不同的表现
6、继承终结者:Final关键字解说
final关键字只能修饰类和方法,不能用来修饰属性和类常量
最终类:使用final关键字修饰的类即为最终类:final class ClassName{},最终类无法被继承
final修饰方法时,该方法能被继承但不能重写
7、抽象类和抽象方法:Abstract关键字解说
使用abstract修饰的类和方法称为抽象类和抽象方法
抽象类不能实例化,只能被继承,
抽象方法只能存在于抽象类或接口中,抽象方法不能有方法体,
继承抽象类的非抽象子类必须实现抽象类中的所有抽象方法,故抽象方法不能使用private修饰
//定义抽象类 abstract class Human{ //声明抽象方法 abstract function display(); //声明普通方法 function fn(){ echo __MATHOD__.'<br>'; } } class Man extends Human{ //重写抽象方法 function display(){ echo 'Man'; } //普通方法不必重写 }
8、接口Interface
接口是类似类的一种结构,使用interface来声明:interface InterfaceName{}
接口不能被实例化,只能被类实现,使用implements关键字:class ClassName implements InterfaceName{}
接口成员:只能定义抽象方法和接口常量
//声明接口 interface Human{ //定义接口常量 const Name = '人'; //定义抽象方法,默认是抽象方法,不能使用abstract关键字修饰 public function eat(); } //实现接口 class Man implements Human{ //实现抽象方法 public function eat(){ echo '男人在吃东西<br>'; } }
抽象类实现接口时不必实现抽象方法
接口的抽象方法必须使用public修饰
实现接口的类不允许重写接口常量,不允许增加方法控制权限,接口可以多继承接口,依然是使用extends关键字
interface Ship{} interface Aerocraft{} interface Airship extends Ship,Aerocraft{}
9、解决单继承问题的代码复用机制trait
trait也是一种类似class的关键字:trait TraitName{}
trait中可以拥有类中除常量外的其他所有成员,包括抽象方法,trait不能被实例化和继承
在类中使用trait代码需要使用use关键字:class ClassName{ use TraitName;}
在类中use了具体类时,相当于trait中的代码在类中写了一遍。
一个类中可以使用多个trait
trait t1{ function f1(){ echo "string"; } } trait t2{ function f2(){} } class C{ use t1,t2; function f3(){ $this->f1(); $this->f2(); } }
使用的多个trait中成员重名时
trait t1{ function f1(){ echo "string"; } } trait t2{ function f1(){} } class C{ use t1,t2{ t2::f1 insteadof t1; //表示f1引用的t2中的f1 t2::f1 as f2; //重命名t2中的f1为f2,不写这句则t2::f1无法被使用 } function f3(){ $this->f1(); $this->f2(); } }
类中不允许属性和trait中的属性同名,方法同名时,类中的方法会覆盖trait中的同名方法,trait中的方法会覆盖继承来的同名方法。
允许类使用别名的方式放松方法访问控制权
trait t1{ private function f1(){ echo "string"; } } class C{ use t1{ f1 as public f2; } } $c = new C(); $c->f2();
10、魔术方法
PHP所提供的"重载"(overloading)是指动态地"创建"类属性和方法,是通过魔术方法来实现的。
当调用当前环境下未定义或不可见的类属性或方法时,重载方法会被调用。(屏蔽错误)
所有的重载方法都必须被声明为 public。
属性重载只能在对象中进行。在静态方式中,这些魔术方法将不会被调用。所以这些方法都不能被 声明为 static。
这些魔术方法的参数都不能通过引用传递。
---------------------
php重载的内容引用了:
作者:和尚周
来源:CSDN
原文:https://blog.csdn.net/csdn_heshangzhou/article/details/80990687
__construct 构造方法
__destruct 析构方法
__clone 克隆方法
__toString
实现该函数可在echo一个对象时显示一个提示 function __toString(){ return $tipstrmsg;}
__call
实现该方法后调用类中不存在的方法时,显示调用不存在信息 function __call($i,$j){ //$i接收方法名,$j接收参数数组}
__callStatic()
描述:用静态方式中调用一个不可访问方法时,__callStatic() 会被调用。public static function __callStatic ( string $name , array $arguments )
__get
访问类中无权访问的成员时调用该方法提示信息 function __get($i){ //$i访问的成员}
__set
设置类中无权设置的成员时调用该方法提示信息 function __set($i,$j){ //$i要设置的成员,$j要设置的值}
__isset
查看类中无权查看的成员 function __isset($i){echo "您无权查看{$i}是否存在!";}
__unset
删除类中无权删除的成员 function __unset($i){echo "您无权删除{$i}!";}
测试代码:
class ClassName{ private $a = 1; private function pri(){} public static function s(){} public function __get($var){ echo "<br>Error:属性{$var}无法访问!<br>"; } public function __set($var,$value){ echo "<br>Error:无权设置属性{$var}的值!<br>"; } public function __isset($var){ echo "<br>Error:您无权查看{$var}是否存在!<br>"; } public function __unset($var){ echo "<br>Error:您无权删除{$var}!<br>"; } public function __call($func,$args){ echo "<br>Error:方法{__MATHOD__}不可访问!<br>"; } public static function __callStatic($func,$args){ echo "<br>Error:静态方法{__MATHOD__}不可访问!<br>"; } public function __toString(){ return 'object('.__CLASS__.')'; } } $c = new ClassName(); echo $c->a; $c->a = 3; isset($c->a); unset($c->a); $c->pri(); $c->s(); echo $c;
测试结果: