1. 程式人生 > 遊戲攻略 >《原神攻略》2.1版本更新內容通知 2.1版新角色與活動前瞻

《原神攻略》2.1版本更新內容通知 2.1版新角色與活動前瞻

面向物件之繼承

一、什麼是繼承

物件的繼承是指從一個類派生出另外的一個類的過程,就像孩子是從父母那裡繼承品性一樣。

  • 關鍵字 extends
  • PHP只能有一個父類
  • 關鍵詞 instanceof 可以用來檢視一個特別的物件是不是屬於一種特定的類的型別
require 'demo.class.php';
$obj = new ChildClass();
if( $obj instanceof Demo ){
    $obj->test();
}

1、全部繼承

子類繼承(也就是具有)父類的全部屬性和方法

class Person
{
    public $name;
    public $age;
    public $info;

    public function __construct($name,$age,$info)
    {
        $this->name = $name;
        $this->age = $age;
        $this->info = $info;
    }

    public function talk(){
        return '你好面試官,我叫' . $this->name . ',今年'.$this->age . ',特長:'. $this->info; 
    }
}

class Man extends Person
{

}

$jack = new Man('jack',18,'帥的令人髮指');
echo $jack->talk();

2、部分繼承

子類還可以新增自己的成員,從而可以保持和父類有所區別

class Man extends Person
{
    public function checkAge(){
        return $this->age>=18 ? '拉出去當壯丁' : '還是小鮮肉';
    }
}

$jack = new Man('jack',18,'帥的令人髮指');
echo $jack->talk();
echo $jack->checkAge();

3、無限多子繼承

class Man extends Person
{
    public function checkAge(){
        return $this->age>=18 ? '拉出去當壯丁' : '還是小鮮肉';
    }
}

class Women extends Person {

}

二、訪問控制

封裝 我們為什麼要使用面向物件程式設計呢?既然只需要使用方法就可以寫出複雜且實用的網站? OOP的真正價值在於封裝,它的意義在於將相互關聯的一組值和函式封裝在一起,組成一個程式設計單元

封裝的概念 : 通過修飾符 改變成員屬性或者成員方法的訪問許可權,達到保護的作用。

修飾符 public protected private
本類內 Y Y Y
子類內 Y Y N
外部 Y N N

類的屬性和成員方法在哪裡可以用、可以被訪問

class User extends Demo
{
    public $username = 'jack';
    protected $truename = '老聶';
    private $age = '18';

    public function printInfo(){
        echo $this->username; 
        echo $this->truename;
        echo $this->age;
    }

    private function secret(){
        echo "這是個祕密!";
    }
}
  • 一個公共的(Public)成員可以從任何一個地方訪問:類本身內部,派生的子類和其他類。
  • 類的受保護的(protected)成員只能在類本身以及子類中訪問。
  • 私有(private)的限制是最嚴格的,這些成員只能在宣告它們的類中進行訪問。私有的類成員不能被子類或者這些類的一個物件例項訪問到。

聶哥友情備註:作為一個慣例,私有變數名通常以一個下劃線開始。這在很多面向物件程式語言中都是這樣做的,即便它並不是必須這樣做

訪問修飾符的範圍

子類複寫父類中的方法時,子類中的 訪問修飾符的範圍要大於等於 父類的【 繼承只能發揚光大,至少保持不變。不可以丟失東西。

在UML中的體現

  • + 公共的
  • - 私有的
  • # 受保護的

三、繼承中的構造方法和析構方法

在子類裡父類的建構函式會不會執行,分兩種情況:

  1. 如子類不定義建構函式 __construct(),則父類的建構函式預設會被繼承下來,且會自動執行。
  2. 如子類定義了建構函式 __construct(),因為建構函式名也是__construct(),所以子類的建構函式實際上是覆蓋(override)了父類的建構函式。這時執行的是該子類的建構函式
class Demo
{
    function __construct()
    {
        echo '正在進行構造...<br/>';
    }
    function test(){
        echo '這是什麼地方<br/>';
    }
    function __destruct()
    {
        echo '正在進行析構...<br/>';
    }
}
class ChildClass extends Demo
{
    function __construct()
    {
       //如果要在子類裡執行父類的建構函式
       //parent::__construct();
        echo '我是後代建構函式-正在進行構造...<br/>';
    }
}

注意 parent::__construct(); 語句不一定必須放在子類的建構函式中。放在子類的建構函式中僅僅保證了其在子類被例項化時自動執行。

四、重寫

過載就是函式或者方法有相同的名稱,但是引數列表不相同的情形,這樣的同名不同引數的函式或者方法之間,互相稱之為過載函式或者方法。PHP不支援,但可用構造方法實現。

重寫又叫覆蓋,就是將父類繼承下來的屬性或方法重新定義,只有保護的或公共的屬性或方法能夠被重寫

1、重寫一個方法,子類定義的方法必須和父類的方法具有完全相同的名稱和引數數量

class Person
{
    public $name;
    public $age;
    public $info;

    public function __construct($name,$age,$info)
    {
        $this->name = $name;
        $this->age = $age;
        $this->info = $info;
    }

    public function talk($fuhao){
        return '你好面試官,我叫' . $this->name . ',今年'.$this->age . ',特長:'. $this->info; 
    }
}

class Man extends Person
{
    public function checkAge(){
        return $this->age>=18 ? '拉出去當壯丁' : '還是小鮮肉';
    }

    public function talk(){

    }
}

2、PHP5.3+ 方法重寫必須要相同個數的引數,如果非多個引數,這時要給其他引數設定預設值

class Person
{
    public $name;
    public $age;
    public $info;

    public function __construct($name,$age,$info)
    {
        $this->name = $name;
        $this->age = $age;
        $this->info = $info;
    }

    private function talk($fuhao){
        return '你好面試官,我叫' . $this->name . ',今年'.$this->age . ',特長:'. $this->info; 
    }
}
class Man extends Person
{
    public function checkAge(){
        return $this->age>=18 ? '拉出去當壯丁' : '還是小鮮肉';
    }

    public function talk($fuhao='沒辦法,我是來充數的'){

    }
}

3、私有屬性或私有方法的重寫問題

  1. 私有屬性和方法不能覆蓋,但其實子類可以定義跟父類私有的同名屬性或方法,只是當做一個自身的新屬性或方法來看待而已

引數必須保持一致(PHP5.4前)

class A
{
    private $name = '山炮';
    public function getName()
    {
        return $this->name;
    }
}
class B extends A
{
    private $name = '二貨';

    public function getTest()
    {
        return $this->getName().$this->name;
    }
}
$b = new B;
echo $b->getTest();//山炮二貨

3.2 訪問私有屬性 類中的私有屬性或者方法是不能被繼承的,但是當一個父類A中的方法FunA,呼叫了父類A中的Private私有屬性或著方法的時,這個FunA在被繼承以後,將能繼續通過$this訪問父類A中的Private私有屬性或者方法,無論繼承子類中對父類A中的私有屬性或方法如何重新實現,直到FunA在繼承子類中被重寫

class A
{
    private $name = '山炮';
    public function getName()
    {
        return $this->name;
    }
}
class B extends A
{
    public $name = '二貨';

}
$b = new B;
echo $b->name; //二貨
echo $b->getName(); //山炮

4、構造方法重寫問題,比較寬鬆,重寫的時候引數可以不一致。

class Person
{
    public $name;
    public $age;
    public $info;

    public function __construct($name,$age,$info)
    {
        $this->name = $name;
        $this->age = $age;
        $this->info = $info;
    }

    private function talk($fuhao,$cans=''){
        return '你好面試官,我叫' . $this->name . ',今年'.$this->age . ',特長:'. $this->info; 
    }
}

class Man extends Person
{
    public function __construct()
    {
        echo '我的方法沒有引數';
    }
}

$jack = new Man();

5、非完全重寫

class Person
{
    public $name;
    public $age;

    public function __construct($name,$age)
    {
        $this->name = $name;
        $this->age = $age;
    }

    public function talk(){
        return '你好面試官,我叫' . $this->name . ',今年'.$this->age; 
    }
}

class Man extends Person
{
    public $info;
    public function __construct($name,$age,$info)
    {
        parent::__construct($name,$age);
        $this->info = $info;
    }

    public function talk(){
        return '我先敲門!'.parent::talk().',特長:'.$this->info;
    }
}

$jack = new Man('jack',18,"帥的令人髮指");

echo $jack->talk();

五、不允許繼承或重寫 final

1.類裡絕大部分方法,都是可以重寫的。唯一的例外就是被定義了FINAL的方法:
final function myFunc(){

}
  • 屬性不能被定義為 final,只有類和方法才能被定義為 final。
  • final關鍵字應該放在其他修飾符protect/public/private/static之前。
  • 定義為final的方法不能被任何子類所重寫。
  • 類也可以宣告為final,這意味著它不能被擴充套件。
2. 不能繼承的類
final A{

}


來自為知筆記(Wiz)