2018-3-6 对象的继承

对象继承:

A具有某些特征,类B也具有A类的所有特征,同时具有自己更多的一些特征,此时发现,B类使用A的特征信息并继续添加自己的一些特有特征信息。我们可以说B类继承于A类。

class jizuidongwu{
    public $prop1 = "有脊椎";
    function show1(){
        echo "<br />特征:" . $this->prop1;
    }

}
class human extends jizuidongwu{  //human继承于jizuidongwu
    public $prop2 = "两脚走路";
    function show2(){
        echo "<br />特征:" . $this->prop2;
    }
}
$person1 = new human();
$person1->show1();  //$person1是human的对象,但可以执行jizuidongwu的方法
$person1->show2();

 

概念:

继承:一个类从另一个已有的类获得属性,称为继承。

派生:从一个已有的类产生一个新的类,称为派生。

 

父类/子类:已有类为父类,新建类为子类。父类也叫“基类”,子类也叫“派生类”

 

单继承:一个类只能从一个上级类继承其特性信息。PHP和大多数面向对象的语言都是单继承模式。C++是多继承。

访问(权限)修饰符:

在类中的成员,通常都可以在前面加上以下3个修饰符:

public:公共的,共有的,公开的

protected:受保护的

private:私有的

访问位置:

1、private某个类的内部;

 

class C{
    private $p1 = 1;
    public function showInfo(){
        echo "<br />属性p1=" . $this->p1;
    }
}
class D extends C{
    private $p2 = 2;
    public function showInfo2(){
        echo "<br />属性p1=" . $this->p1;//访问的是上级的似有成员$p1
        echo "<br />属性p2=" . $this->p2;//访问的是自己的私有成员$p1
    }
}
$d1 = new D();
$d1->showInfo2();
echo "<br />在类外p2=" . $d1->p2;//这一行出错,因为在“外面”不能访问私有成员$p2

 

2、protected某个类及其子类的内部;

 

class C{
    protected $p1 = 1;
    public function showInfo(){
        echo "<br />属性p1=" . $this->p1;
    }
}
class D extends C{
    protected $p2 = 2;
    public function showInfo2(){
        echo "<br />属性p1=" . $this->p1;//访问的是上级的受保护成员$p1
        echo "<br />属性p2=" . $this->p2;//访问的是自己的受保护成员$p1
    }
}
$d1 = new D();
$d1->showInfo2();
echo "<br />在类外p2=" . $d1->p2;//这一行出错,因为在“外面”不能访问受保护成员$p2

 

3、public所有位置,内部和外部都可以使用;

class C{
    public $p1 = 1;
    public function showInfo(){
        echo "<br />属性p1=" . $this->p1;
        echo "<br />属性p2=" . $this->p2;//此时可以访问下级的$p2(但很不常用)
    }
}
class D extends C{        //D继承于C
    public $p2 = 2;
    public function showInfo2(){
        echo "<br />属性p1=" . $this->p1;//访问的是上级的$p1(常见情形)
        echo "<br />属性p2=" . $this->p2;
    }
}
$d1 = new D();
$d1->showInfo2();
echo "<br />在类外p2=" . $d1->p2;  //说明在类外也可以调用public $p2 = 2;
$d1->showInfo();

此时输出结果为:

属性p1=1
属性p2=2
在类外p2=2
属性p1=1
属性p2=2

总结以上,访问修饰限定符的使用范围:

范围

本类内

继承关系类内

类外

public

可以

可以

可以

protected

可以

可以

不可以

private

可以

不可以

不可以

parent代表父类:

self代表“本类”;

parent通常用于在子类中调用父类的成员的时候使用,多数通常就是使用父类的“静态类”成员。

class C{
    public $p1 = 1;
    function showMe(){
        echo "<br />我是父类,数据有:";
        echo "<br />C中p1=" . $this->p1;
    }
    function __construct($p1){
        $this->p1 = $p1;
    }
}
class D extends C{
    public $p2 = 2;
    function __construct($p1,$p2){
        //经典用法
        parent::__construct($p1);//调用父类的构造函数来初始化p1
        $this->p2 = $p2;    //初始化p2
    }
    function showMe2(){
        echo "<br />我是子类,数据有:";
        //基本用法:
        parent::showMe();    //调用父类的showMe方法,
        echo "<br />D中p2=" . $this->p2;
    }
}
$d1 = new D(10,20);    //此时就需要尊照构造函数的参数结构来使用
$d1->showMe2();    

构造方法和析构方法在继承中的表现:

子类中没有定义构造方法时,会自动调用父类的构造方法。因此实例化子类时,需按照父类的构造方法的形式进行。

 

class C{
    public $p1 = 1;
    public $p3 = 3;
    function __construct($p1,$p3){   //设置父类的构造方法
        echo "<br />父类构造方法调用了";
        $this->p1 = $p1;
        $this->p3 = $p3;
    }
}
class D extends C{
    public $p2 = 2;
    function __construct($p1,$p2, $p3){  //设置子类的构造方法
        echo "<br />子类构造方法调用了";
        parent::__construct($p1,$p3);  //调用父类构造方法
        $this->p2 = $p2;
    }
    function showInfo(){  //方法名
        echo "<br />p1=$this->p1";
        echo "<br />p2=$this->p2";
        echo "<br />p3=$this->p3";
    }
}
$d1 = new D(10, 20, 30);  //新建对象$d1
$d1->showInfo();  //调用方法

很多时候,在构造方法中,子类都可以通过调用父类的构造方法节省代码,增加可读性。

 

当子类定义了自己的析构方法后,则就不会自动调用父类的析构方法的,但可以手动调用:parent::__destruct()

重写:

重写又叫覆盖,将从父类继承下来的属性或方法重新“定义”。重写发生在父类底下的子类中。

class Jizhuidongwu{
    public $p1 = "具有脊椎";
    function showMe(){  //父类方法
        echo "<br />我是脊椎动物,特征为:";
        echo "<br />属性p1=" . $this->p1;
    }
}
class Human extends Jizhuidongwu{
    public $p1 = "具有28节脊椎骨的脊椎";//28是假设
    public $p2 = '有32颗牙齿';
    function showMe(){  //重写方法
        echo "<br />我是人类,特征为:";
        //echo "<br />属性p1:" . $this->p1;
        //实际应用中,通常上一行(显示父类信息)会使用下一行代替
        parent::showMe();    //这样可以更节省
        echo "<br />属性p2:" . $this->p2;
    }
}
$h1 = new Human();
$h1->showMe();

重写具有一定的要求,主要就是访问权限以及参数。

访问权限方面,下级的访问权限应不低于上级的访问权限。

上级:public  下级:只能public

上级:protected  下级: protected, public

上级:private   下级:private  protected  public——实际此情况无意义。

方法的参数形式应该与父类的保持一致。

构造方法在重写的时候参数可以不一致。

最终类final class:

最终类不会再继续往下拓展,即这就是最底下的类,可以定义对象,不能有子类。

形式:final class 类名{     类定义     }

最终方法 final  method:这个方法不会被下级类覆盖。

final  function  方法名(){    方法定义     }

设计模式:解决问题的常用做法,比较好的经验总结。针对不同问题,有不同的解决办法,这就是不同的设计模式。

工厂模式:有时候,我们需要实例化许多类,用来得到对象。

设计一个“工厂”(类)作用是“生产”各种对象。通常这种工厂,只需要制定类名,就可以获取一个该类的对象。

class factory{
    //Instance表示“实例”,“对象”
    static function getInstance($className){
        if(file_exists('./class/' . $className . ".class.php")){
            $obj1 = new $className();
            return $obj1;
        }
        else{
            return null;//也可以die();
        }
    }
}
$obj1 = factory::getInstance("A");//获取类A的一个对象
$obj2 = factory::getInstance("B");//获取类B的一个对象
$obj3 = factory::getInstance("A");//再获取类A的一个对象

 

posted @ 2018-03-06 19:12  凉冰婵  阅读(199)  评论(0编辑  收藏  举报