PHP面向對象

面向對象

面向對象基礎

面向對象

什麼是類?

具備相同屬性(特徵)和方法(行爲)的一系列個體的集合,類是一個抽象的概念。php

什麼是對象?

從類中,拿到的具備具體屬性值的個體,稱爲對象。對象是一個具體的個體。
eg:人類;張三數組

類和對象的關係?

  • 類是對象的抽象化!對象是類的具體化!
  • 類僅僅代表這類對象有哪些屬性,可是不能有具體的值,因此類是抽象的。
  • 對象是將類的全部屬性賦值後,產生具體的個體,全部對象是具體的。

類的聲明與實例化

如何聲明一個類:

class 類名{
    訪問修飾符 $屬性[=默認值];
    [訪問修飾符] function 方法(){}
}
class SimpleClass {
    // property declaration
    public $var = 'a default value';

    // method declaration
    public function displayVar() {
        echo $this->var;
    }
}

聲明一個類的注意事項:

  • 類名只能有字母數字下劃線組成,開頭不能是數字,必須符合大駝峯法則;
  • 類名必須使用class修飾,類名後面必定不能有();
  • 屬性必需要帶訪問修飾符,方法能夠不帶訪問修飾符。

實例化對象及對象屬性方法的調用:

$對象名 = new 類名(); //()能夠不帶函數

類外部調用屬性和方法:

$對象名 -> $屬性名; //使用->調用屬性時,屬性名不能帶$符號this

類內部調用屬性和方法:

$this -> $屬性名;spa

構造函數

什麼是構造函數?

構造函數是類中的一個特殊函數,當咱們使用new關鍵字實例化對象時,至關於調用了類的構造函數。code

構造函數有什麼做用?

實例化對象時,自動調用,用於給對象的屬性賦初值!orm

構造函數的寫法:

  • 構造函數名,必須與類同名(廢棄)
[public] function Person($name){
    $this -> name = $name;
}
  • 使用魔術方法__construct
[public] function __construct($name){
    $this -> name = $name;
}

構造函數注意事項:

  • 第一種寫法,構造函數名必須與類同名!!!!
  • 若是一個類沒有手寫構造函數,則系統默認會有一個空參構造,所以可使用new Person();
  • 若是咱們寫了帶參數的構造函數,則將不會再有空參構造,也就是不能直接使用new Person();
  • Person後面的()中的參數列表,必須符合構造函數的要求!!!!
  • 若是兩種構造函數同時存在,將使用__construct

析構函數:__destruct():

  • 析構函數在對象被銷燬釋放以前自動調用;
  • 析構函數不能帶有任何的參數;
  • 析構函數經常使用於對象使用完之後,釋放資源,關閉資源等。

魔術方法:

PHP中,給咱們提供一系列用__開頭的函數,這些函數無需本身手動調用,
會在合適的時機自動調用,這類函數稱爲魔術稱爲魔術函數。
eg:function __construct(){} 在類new一個對象時自動調用
function __destruct(){} 在對象被銷燬時自動調用,咱們要求,除了魔術方法以外,自定義的函數與方法不能使用__開頭。最後,通常對於功能比較複雜的類,咱們會單獨的寫到一個類文件中。類文件的命名,同一小寫,使用"類名小寫.class.php"的方式命名。在其餘文件中使用這個類時,可使用include導入這個".class.php"文件。對象

封裝和繼承

什麼是封裝?

經過訪問修飾符,將類中不須要外部訪問的屬性和方法進行私有化處理,以實現訪問控制。繼承

注意:是實現訪問控制,而不是拒絕訪問。也就是說,咱們私有化屬性後,須要提供對應的方法,讓用戶經過咱們提供的方法處理屬性。接口

封裝的做用?

  • 使用者只關心類可以提供的功能,不關心功能實現的細節!(封裝方法)
  • 對用戶的數據進行控制,防止設置不合法數據,控制返回給用戶的數據(屬性封裝+set/get方法)

實現封裝操做?

方法的封裝

對於一些只在類內部使用的方法,而不像對外部提供使用,那麼,這樣的方法咱們可使用private進行私有化處理。

private function formatName(){} //這個方法僅僅能在類內部使用$this調用
function showName(){
    $this->formatName();
}

屬性的封裝+set/get方法

爲了控制屬性的設置以及讀取,能夠將屬性進行私有化處理,並要求用戶經過咱們提供的set/get方法進行設置

private $age;
//set方法
function setAge($age){
    $this->age=$age;
} 
//get方法
function getAge(){
     return $this->age;
}
$對象->getAge();
$對象->setAge(12);

屬性的封裝+魔術方法

__get( -> __set(, ->= }
$對象->age; //訪問對象私有屬性時,自動調用__get()魔術方法,而且將訪問的屬性名傳給__get()方法;
$對象->age=12; //設置對象私有屬性時,自動調用__set()魔術方法,而且將設置的屬性名以及屬性值傳給__set()方法;

注意:在魔術方法中,可使用分支結構,判斷$key的不一樣,進行不一樣操做。

關於封裝的魔術方法:

  • __set($key,$value):給類私有屬性賦值時自動調用,調用時給方法傳遞兩個參數:須要設置的屬性名,屬性值。
  • __get($key,$value):讀取類私有屬性時自動調用,調用時給方法傳遞一個參數,須要讀取的屬性名;
  • __isset($key):外部使用isset()函數檢測私有屬性時,自動調用。

    類外部使用isset();檢測私有屬性,默認是檢測不到的。false
    因此,咱們可使用__isset();函數,在自動調用時,返回內部檢測結果。

  • function __isset($key){return isset($this -> $key);}

    當外部使用isset($對象名->私有屬性);檢測時,將自動調用上述__isset()返回的結果!

  • __unset($key):外部使用unset()函數刪除私有屬性時,自動調用;
    function __unset($key){unset($this -> $key);}

    當外部使用unset($對象名->私有屬性);刪除屬性時,自動將屬性名傳給__unset(),並交由這個魔術方法處理。

繼承的基礎知識:

如何實現繼承?

給子類使用extends關鍵字,讓子類繼承父類;

class Student extends Person{}

現繼承的注意事項?

  • 子類只能繼承父類的非私有屬性。
  • 子類繼承父類後,至關於將父類的屬性和方法copy到子類,能夠直接使用$this調用。
  • PHP只能單繼承,不支持一個類繼承多個類。可是一個類進行多層繼承。
class Person{}
class Adult extends Person{}
class Student extends Adult{} 
//Student 類就同時具備了Adult類和Person類的屬性和方法

方法覆蓋(方法重寫)

  • 子類繼承父類
  • 子類重寫父類已有方法

    符合上述兩個條件,稱爲方法覆蓋。覆蓋以後,子類調用方法,將調用子類本身的方法。
    一樣,除了方法覆蓋,子類也能夠具備與父類同名的屬性,進行屬性覆蓋。

若是,子類重寫了父類方法,如何在子類中調用父類同名方法?

partent::方法名();
因此,當子類繼承父類時,需在子類的構造中的第一步,首先調用父類構造進行復制。

function __construct($name,$sex,$school){
    partent::__construct($name,$sex);
    $this -> school = $school;
}

PHP關鍵字

final

  • final修飾類,此類爲最終類,不能被繼承!
  • final修飾方法,此方法爲最終方法,不能被重寫!
  • final不能修飾屬性。

static

  • 能夠修飾屬性和方法,分別稱爲靜態屬性和靜態方法,也叫類屬性,類方法;
  • 靜態屬性,靜態方法,只能使用類名直接調用。

    使用"類名::\(靜態屬性" , "類名::靜態方法()" `Person::\)sex; Person::say();`

  • 靜態屬性和方法,在類裝載時就會聲明,先於對象產生。
  • 靜態方法中,不能調用非靜態屬性或方法;

    非靜態方法,能夠調用靜態屬性和方法。 (由於靜態屬性和方法在類裝載時已經產生,而非靜態的屬性方法,此時尚未實例化誕生)

  • 在類中,可使用self關鍵字,代指本類名。
class Person{
    static $sex = "nan";
    function say(){
        echo self::$sex;
    }
}
  • 靜態屬性是共享的,也就是new出不少對象,也是共用一個屬性。

const關鍵字:

在類中聲明常量,不能是define()函數!必須使用const關鍵字。與define()聲明類似,const關鍵字聲明常量不能帶$,必須所有大寫!
常量一旦聲明,不能改變。調用時與static同樣,使用類名調用Person::常量

instanceof操做符:

檢測一個對象,是不是某一個類的實例。(包括爹輩,爺爺輩,太爺爺輩……)

$zhangsan instanceof Person;

【小總結】幾種特殊操做符:

  • . 只能鏈接字符串; "".""
  • => 聲明數組時,關聯鍵與值["key"=>"value"]
  • -> 對象($this new出的對象)調用成員屬性,成員方法;
  • :: 使用parent關鍵字,調用父類中的同名方法:parent::say();,使用類名(和self)調用類中的靜態屬性,靜態方法,以及常量。

魔術方法小總結

  • __construct():構造函數,new一個對象時,自動調用。
  • __destruct():析構函數,當一個對象被銷燬前,自動調用。
  • __get():訪問類中私有屬性時,自動調用。傳遞讀取的屬性名,返回$this->屬性名
  • __set():給類的私有屬性賦值時,自動調用。傳遞須要設置的屬性名和屬性值;
  • __isset():使用isset()檢測對象私有屬性時,自動調用。傳遞檢測的屬性名,返回isset($this -> 屬性名);
  • __unset():使用unset()刪除對象私有屬性時,自動調用。傳遞刪除的屬性名,方法中執行unset($this -> 屬性名);
  • __toString():使用echo打印對象時,自動調用。返回想要在打印對象時,顯示的內容;返回必須是字符串;
  • __call():調用一個類中未定義或未公開的方法時,自動調用。傳遞被調用的函數名,和參數列表數組;
  • __clone():當使用clone關鍵字,克隆一個對象時,自動調用。做用是爲新克隆的對象進行初始化賦值;
  • __sleep():對象序列化時,自動調用。返回一個數組,數組中的值就是能夠序列化的屬性;
  • __wakeup():對象反序列化時,自動調用。爲反序列化新產生的對象,進行初始化賦值;
  • __autoload():須要在類外部聲明函數。當實例化一個未聲明的類時,自動調用。傳遞實例化的類名,可使用類名自動加載對應的類文件。

抽象類和抽象方法

  • 什麼是抽象方法?
    沒有方法體{}的方法,必須使用abstract關鍵字修飾。這樣的方法,咱們稱爲抽象方法。
abstract function say(); //抽象方法

什麼是抽象類?

使用abstract關鍵字修飾的類就是抽象類。

abstract class Person{}

抽象類的注意事項:

  • 抽象類能夠包含非抽象方法;
  • 包含抽象方法的類必須是抽象類,抽象類並不必定必須包含抽象方法;
  • 抽象類,不能實例化。(抽象類中可能包含抽象方法,抽象方法沒有方法體,實例化調用沒有意義)
    咱們使用抽象類的目的,就是限制實例化!!!
  • 子類繼承抽象類,那麼子類必須重寫父類的全部抽象方法,除非,子類也是抽象類。

使用抽象類的做用?

  • 限制實例化。(抽象類是一個不完整的類,裏面的抽象方法沒有方法體,因此不能實例化)
  • 抽象類爲子類的繼承提供一種規範,子類繼承一個抽象類,則必須包含而且實現抽象類中已定的抽象方法。

接口與多態

接口

什麼是接口?

接口是一種規範,提供了一組實現接口的類所必須實現的方法組合。
接口使用interface關鍵字聲明;

interface Inter{}
  • 接口中的全部方法,必須都是抽象方法。
  • 接口中的抽象方法不須要也不能使用abstract修飾。
  • 接口中不能聲明變量,不能有屬性,只能使用常量!!!

接口能夠繼承接口,使用extends關鍵字!

接口使用extends繼承接口,能夠實現多繼承。

interface int1 extends Inter,Inter2{}

類能夠實現接口,使用implements關鍵字!

類使用implements實現接口,可同時實現多個接口,多個接口間逗號分隔;

abstract class Person implements Inter,Inter2{}

一個類實現一個或多個接口,那麼這個類,必須實現全部接口中的全部抽象方法!
除非,這個類是抽象類。

接口&&抽象類區別

  • 聲明方式上,接口使用interface關鍵字,抽象類使用abstract class
  • 實現/繼承方式上,一個類使用extends繼承抽象類,使用implements實現接口。
  • 抽象類只能單繼承,接口能夠多實現。(接口extends接口)、多實現(類implements接口)
  • 抽象類中能夠有非抽象方法,接口中只能有抽象方法,不能有費抽象方法。抽象類中的抽象方法必須使用abstract關鍵字修飾,接口中抽象方法不能帶修飾詞。
  • 抽象類是個類,能夠有屬性、變量;接口中只能有常量。

多態

多態

一個類,被多個子類繼承。

若是,這個類的某個方法,在多個子類中,表現出不一樣的功能,咱們稱這種行爲爲多態。

實現多態的必要途徑:
  • 子類繼承父類;
  • 子類重寫父類方法;
  • 父類引用指向子類對象
相關文章
相關標籤/搜索