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;

测试结果:

 

posted @ 2019-02-15 16:08  chuanzi  阅读(341)  评论(0编辑  收藏  举报