PHP的面向對象解析

面向對象

早期編程因爲受電腦硬件限制,程序都是追求效率,而忽略可理解性,擴充性,隨着硬件技術的發展,編程愈來愈重視多人開發,程序員愈來愈重視程序的可靠性,可擴展性,可維護性,因此刺激了程序語言的發展php

面向過程程序員

  • 程序員設計好程序代碼流程圖,輔助程序設計。優勢:用什麼功能就編寫什麼函數 缺點:數據管理上比較混亂 ,主要集中在函數成面上,面向對象把屬性和方法進行封裝,更好的可重用性和可擴展性

面向對象面試

  • 萬物皆對象,將構成問題的事務分解到各個對象上,創建對象的目的不是爲了完成一個工做,而是爲了描述某個事務在解決問題中的行爲,更符合人的思惟習慣,代碼重用性高,可擴展性好
面向對象和麪向過程的核心區別是如何分配職責。

類和對象

面向對象是由一系統具備屬性和方法的對象構成,對象之間相互交互 ,從而實現業務需求。sql

屬性數據庫

  • 在類中定義的變量,即爲成員屬性,用於描述對象靜態特性的數據。如人的姓名,性別,首字母小寫

方法編程

  • 函數定義在類中即爲成員方法,用於描述對象動態特性的操做行爲,方法名不區分大小寫,不可重名,首字母小寫

對象生命週期服務器

  • 建立後,生命週期開始,當程序結束後或程序員清除對象後即銷燬,PHP會自動銷燬對象

類是一種抽象的概念,是具備相同語義定義對象的集合(具備相同屬性和方法的集體),使用具體的類是不可行的,只能實例化。拿汽車舉例,汽車的設計圖紙就是類,汽車是對象。設計中重點是類的建立微信

類名書寫規範架構

  • 類名首字母大寫
  • 一個類定義在一個文件中

$this

對象中使用 $this 指針能夠訪問屬性或方法。併發

class Code
{
    protected $len = 5;
    public function make()
    {
        return $this->len . $this->show();
    }
    public function show()
    {
        return ' : is show';
    }
}
echo (new Code)->make();

繼承

經過使用 extends 能夠繼承父類的屬性與方法,在PHP中繼承是單一的。

class Notify
{
    public function message()
    {
        return 'notify message';
    }
}
class User extends Notify
{ }
echo (new User)->message();

父類調用

子類可使用 parent 關鍵字調用父類方法

...
public function message()
{
	return parent::message();
}
...

方法重寫

子類能夠重寫父類的方法,除非父類的方法沒有使用 final 修飾。

class Notify
{
    public function message()
    {
        return 'notify message';
    }
}
class User extends Notify
{
    public function message()
    {
        return 'user notify';
    }
}
echo (new User)->message();

禁止重寫

使用final聲明的方法,將禁止在子類中重寫父類方法。

public final function message()
{
	return 'notify message';
}

封裝

public 公有

  • 在類的內部與外部或子類均可以訪問,是最開放的權限

private 私有

  • 定義類的屬性和方法,在類的內部能夠訪問,在類的外部或子類都不能夠訪問

protected 受保護

  • 定義類的屬性和方法,在類的內部或子類能夠訪問,類的外部不能夠訪問

模塊設計

  • 強內聚(功能儘可能在類的內部完成),弱耦合(開放盡可能少的方法給外部調用)。例:公司銷售接項目,具體工做交給公司內部程序員,設計人員,服務器管理人員協同完成

trait

使用trait 機制能夠變相的使用多重繼承。

class Alipay
{
    use Pay;
}
class WePay
{
    use Pay;
}

trait Pay
{
    public function sn()
    {
        return 'ABCDEF';
    }
}
echo (new WePay)->sn();

若是本類與 trait 中存在同名的屬性和方法時,將使用本類中的屬性與方法。

...
class WePay
{
    use Pay;
    public function sn()
    {
        return __METHOD__;
    }
}

trait Pay
{
    public function sn()
    {
        return 'ABCDEF';
    }
}
...

多個trait

可使用多個 trait 用逗號鏈接

...
use Pay,Site;
...

解決衝突

class WePay
{
    use Pay, Email {
    Pay::notify insteadof Email;
    Email::notify as EmailNotify;
}
trait Pay
{
    public function notify()
    {
        return __METHOD__;
    }
}
trait Email
{
    public function notify()
    { 
    	return __METHOD__;
    }
}
echo (new WePay)->notify();

Pay::notify insteadof Email 表示使用 Pay::notify 方法替代 Email::notify 方法。

Email::notify as EmailNotify` 將`Email:notify` 別名爲 `EmailNotify

訪問控制

能夠爲繼承的 trait 方法從新定義訪問控制

class WePay
{
    use Pay, Email {
    Pay::notify insteadof Email;
    Email::notify as protected EmailNotify;
    ...
}

多重trait

能夠經過多個trait 組合來使用。

trait Notify
{
    public function response()
    {
        return 'notify response';
    }
}
trait Pay
{
    use Notify;
}

class User
{
    use Pay;
}
echo (new User)->response();

抽象方法

trait Notify
{
    public function response()
    {
        return 'notify response' . $this->sn();
    }
    abstract protected function sn();
}
trait Pay
{
    use Notify;
}

class User
{
    use Pay;
    protected function sn()
    {
        return 'SN999';
    }
}
echo (new User)->response();

靜態方法

trait 中可使用靜態方法、抽象方法、靜態屬性。

...
trait Pay
{
    public function sn()
    {
        return 'ABCDEF';
    }
    public static function notify()
    {
        return __METHOD__;
    }
}
class WePay
{
    use Pay;
    ...
}
echo WePay::notify();

static

static:

  • 須要一個數據對象只服務於類,即類內部可用,對外不可用時。建對象是極其耗費資源的,所以當一個方法具備比較強的公用性的時候,沒有必要爲了調用這個方法而從新再生成該類的實例。定義的方法或變量在程序第一次加載時即駐留內存,程序結束釋放。

static變量:

  • 經過static聲明的成員變量爲靜態變量或叫類變量,是該類的公共變量,在第一次使用時即生成,對於該類的全部對象只有一份,是屬於類的,不是屬於對象的。static變量是屬於類而不屬於對象,能夠在任何地方通地類來訪問,是類的全局變量,類建立時即存入內存。對多個對象來講,靜態數據成員只存儲一處,能夠節省內存。只要對靜態數據成員的值更新一次,保證全部對象存取更新後的相同的值。

static方法:

  • 用static聲明的方法爲靜態方法或叫類方法,執行該方法時不會將對象引用傳給函數,因此咱們不能訪問非靜態成員,只能訪問靜態方法或靜態變量。只能使用關於類的方式如self static parent等。使用時不用生成對象便可執行

類常量

使用 const 來定義類常量,常量使用 self::來調用。

class Model implements ArrayAccess, Iterator
{
    use ArrayIterator, Relation, Validate, Auto, Filter;
    //----------自動驗證----------
    //有字段時驗證
    const EXIST_VALIDATE = 1;
    //值不爲空時驗證
    const NOT_EMPTY_VALIDATE = 2;
    ...
}

$this self:: parent::

$this

  • 是當前對象的引用, 通常出如今方法裏,用於獲取類的成員屬性,或執行類的成員方法

self::

  • 對本類的引用 ,用於獲取當前類的表態成員屬性或靜態成員方法self::run()

parent::

  • 對父類的引用,調用父類的方法或屬性。

魔術方法

構造方法&析構方法

構造方法__construct()

  • 在建立對象時自動執行,沒有返回值,用於執行類的一些初始化工做,如對象屬性的初始化工做,構造方法爲__construct()。
  • 能夠在構造方法中傳遞參數,用於定義屬性,在父類和子類都定義構造方法時,執行子類的構造方法

析構方法__destruct():

  • 當全部對象的引用被銷燬時執行。

__get 與__set

讀取不可訪問或不存在的屬性時,__get() 會被調用,同理獲取不可訪問或不存的的屬性時會執行 __set() 方法。

<?php
abstract class Query
{
    abstract protected function record(array $data);
    public function select()
    {
        return $this->record(['name' => '後盾人', 'age' => 33]);
    }
}
class Model extends Query
{
    protected $field = [
        'name'
    ];
		public function all(){
			$this->select();
			return $this->field;
		}
    protected function record(array $data)
    {
        $this->field = $data;
    }
    public function __get($name)
    {
        return $this->field[$name] ?? null;
    }
    public function __set($name, $value)
    {
        $this->field[$name] = $value;
    }
}

$user = new Model;
$user->all();
echo $user->name;
$user->name = '向軍大叔';
echo $user->name;ry

### __isset() 與 __unset()

當使用 isset()函數或者empty()函數 判斷屬性是否存在或者是否爲空的時候會自動觸發。

當使用 unset() 函數判斷屬性時,若是存在__unset() 方法將會執行。

...
public function __unset($name)
{
	if (!isset($this->field[$name]) || in_array($name, $this->deny)) {
		throw new Exception('禁止操做');
	}
}
public function __isset($name)
{
	return isset($this->field[$name]);
}
...

抽象類&抽象方法

具備抽象方法的類爲抽象類,抽象方法即爲沒有內容的空方法,要求子類進行完善內容,抽象類不能實例化,只能繼承,經過extends來實現,抽象類中也能夠定義普通方法

父類方法執行方式不肯定,但子類還都有這個方法

  • 例1:如交通工具類:定義抽象方法控制交通工具運行方式,這樣每一個交通工具如飛機,汽車都要重寫父類方法。若是在父類工具類定義該方法(好比在地上走)沒有任何意義,由於每一個交通工具都要重寫(飛機要重寫方法,船要重寫方法),因此針對你類方法的不肯定性,咱們須要抽象方法,實現多態。

例2:定義動物類,每一個動物都有叫聲方法,可是表面不一樣,因此要定義爲抽象類,讓每種動物類去實現功能。

  • 當父類爲抽象類時,子類必須重寫父類的抽象方法
  • 抽象類裏不必定非要寫抽象方法,但有抽象方法的類必須定義爲抽象類
  • 抽象類必須繼承使用
  • 抽象方法不能有主體即{}
  • <?php abstract class AbstractClass { // 強制要求子類定義這些方法 abstract protected function getValue(); abstract protected function prefixValue($prefix); // 普通方法(非抽象方法) public function printOut() { print $this->getValue(); } }

接口

接口是一組成員聲明方法的集合,包含空的成員方法和常量,空的方法要求繼承類去具體實現。成員方法爲public,屬性爲常量。

    • 例如:現實中的電腦USB或PCI插槽,插線板等都有接口例子

 

繼承是一級一級層次式,若是某一層出現問題,整個繼承就會出現意外。而接口隻影響實現接口的類,接口能夠在破壞原來的繼承基礎上對類擴展。接口能夠實現多繼承。

  • 例:電腦USB接口,規定各個廠商必須構造合適的接口方法,好比手機,數碼相機,網銀U盾。要讓各個廠商寫本身的方法如U盾插到USB上他會自動安裝網銀驅盾,彈出網頁,手機裝上後能夠打開手機裏的內容,同時能夠充電

抽象類及普通類均可以實現接口,經過關鍵字implements

接口與抽象類的區別:

  • 1 接口只能用implements實現 抽象類用extends繼承實現
    2 接口沒有數據成員,能夠定義常量,抽象類能夠有
    3 接口沒有構造函數,抽象類能夠定義構造函數
    4 接口方法都是public 抽象類方法能夠用protected private public來修飾
    5 一個類能夠實現多個接口,但只能繼承一個抽象類
    6 接口中不能夠有成員方法,抽象類能夠有成員方法
interface DbInterface {
    public function connectDb(); //得到鏈接   參數爲表名
    public function close(); //關閉數據庫
    public function exe($sql); //發送沒有返回值的sql
    public function query($sql); //有返回值的sql
}
class Db implements DbInterface
{
	public function exe($sql){
	}
	public function query($sql{
	}
}

以上內容但願幫助到你們,更多PHP大廠PDF面試文檔,PHP進階架構視頻資料,PHP精彩好文免費獲取能夠微信搜索關注公衆號:PHP開源社區,或者訪問:

2021金三銀四大廠面試真題集錦,必看!

四年精華PHP技術文章整理合集——PHP框架篇

四年精華PHP技術文合集——微服務架構篇

四年精華PHP技術文合集——分佈式架構篇

四年精華PHP技術文合集——高併發場景篇

四年精華PHP技術文章整理合集——數據庫篇

相關文章
相關標籤/搜索