面向對象的PHP

作者:網絡 | 發布時間:2020年10月30日 | 閱讀:1603

我(wǒ)們可以想象我(wǒ)們的宇宙是由不同的對象組成,像太陽,地球,月亮等等。同樣我(wǒ)們可以想象我(wǒ)們的車(chē)由不同的組件組成如車(chē)輪,轉向盤,齒輪等。同樣有面向對象編程概念,假設一(yī)切作爲對象使用不同的對象實例化一(yī)個事物(wù)。

面向對象的概念

在我(wǒ)們進入講述細節之前,讓我(wǒ)們首先定義面向對象編程相關的重要術語。

  • 類:這是一(yī)個編程定義的數據類型,包括本地的方法以及本地數據。你能想到的一(yī)個類模闆制作許多相同類型的實例(或類)的對象。

  • 對象:一(yī)個單獨的數據結構用來定義的一(yī)個類的實例。你定義一(yī)個類,然後讓許多對象屬于它。對象也被稱爲實例。

  • 成員(yuán)變量:這是在類的内部定義的變量。這些數據對于外(wài)部類是不可見的,但是可以通過成員(yuán)函數來訪問。對象一(yī)旦創建這些變量被稱該對象的屬性。

  • 成員(yuán)函數:這些函數定義在一(yī)個類,用于訪問對象的數據。

  • 繼承:當一(yī)個類被定義爲繼承一(yī)個已經存在的父類,我(wǒ)們稱這個類爲繼承類,這裏繼承類可以使用父類的一(yī)些成員(yuán)函數和變量。

  • 父類:一(yī)個類被另一(yī)個類繼承。這個類也被稱爲基類或超類。

  • 子類:一(yī)個類繼承另一(yī)個類。這個類也被稱爲一(yī)個子類或派生(shēng)類

  • 多态性:這是一(yī)個面向對象的概念,相同的函數可以用于不同的目的。例如函數名仍将是相同的,但它采取不同的數量的參數,可以做不同的任務,完成不同的工(gōng)作。

  • 重載:一(yī)種多态性的部分(fēn)指在所有的運算符有不同的實現取決于他們的類型參數。同樣的函數也可以重載伴随着不同的實現。

  • 數據抽象:任何表示的數據的實現細節是隐藏(抽象)。

  • 封裝:是指一(yī)個概念,我(wǒ)們的所有數據和成員(yuán)函數封裝在一(yī)起,形成一(yī)個對象

  • 構造函數:指一(yī)個特殊的函數類型可以被自動調用,構造函數的類會在每次創建新對象時先調用此方法。

  • 析構函數:指一(yī)個特殊的函數類型可以被自動調用,會在到某個對象的所有引用都被删除或者當對象被顯式銷毀時執行。

定義的 PHP 類

在 PHP 中(zhōng)定義一(yī)個新類的一(yī)般形式如下(xià):

    <?php
    class phpClass{
       var $var1;
       var $var2 = "constant string";
       function myfunc ($arg1, $arg2) {
          [..]
       }
       [..]
    }
    ?>

這是每一(yī)行的描述:

  • 定義類形式 Class,後面是您想要定義的類的名稱。

  • 一(yī)組花括号包含任意數量的變量聲明和函數定義。

  • 變量聲明開(kāi)始使用 var 的特殊形式,緊随其後的是一(yī)個傳統的 $ 變量名;他們可能也有一(yī)個初始化分(fēn)配一(yī)個常量值。

  • 函數定義看起來很像獨立的 PHP 函數,但該類和将被用于設置和訪問對象數據。

例子

這裏是一(yī)個例子定義了一(yī)個書(shū)籍類型類:

    <?php
    class  Books{
        /* Member variables */
        var $price;
        var $title;
        /* Member functions */
        function setPrice($par){
           $this->price = $par;
        }
        function getPrice(){
           echo $this->price ."<br/>";
        }
        function setTitle($par){
           $this->title = $par;
        }
        function getTitle(){
           echo $this->title ." <br/>";
        }
    }
    ?>

變量 $this 是一(yī)個特殊的變量,它指的是同一(yī)個對象,本身。

用 PHP 創建對象

你一(yī)旦定義好你的類,那麽您可以創建許多對象。下(xià)面是一(yī)個例子,如何使用 new 操作符創建對象。

    $physics = new Books;
    $maths = new Books;
    $chemistry = new Books;

在這裏,我(wǒ)們已經創建了三個對象,這些對象是相互獨立的,他們有自己的單獨存在的空間。接下(xià)來,我(wǒ)們将看到如何訪問成員(yuán)函數和成員(yuán)變量的過程。

調用成員(yuán)函數

創建對象後,您将能夠使用相關的對象調用成員(yuán)函數。一(yī)個成員(yuán)函數将能夠處理相關對象的成員(yuán)變量。

下(xià)面的例子顯示了如何通過調用成員(yuán)函數設置标題和價格三本書(shū)。

    $physics->setTitle( "Physics for High School" );
    $chemistry->setTitle( "Advanced Chemistry" );
    $maths->setTitle( "Algebra" );

    $physics->setPrice( 10 );
    $chemistry->setPrice( 15 );
    $maths->setPrice( 7 );

現在你調用另一(yī)個成員(yuán)函數獲取設置在上面的例子的值:

    $physics->getTitle();
    $chemistry->getTitle();
    $maths->getTitle();
    $physics->getPrice();
    $chemistry->getPrice();
    $maths->getPrice();

這将會産生(shēng)以下(xià)結果:

    Physics for High School
    Advanced Chemistry
    Algebra
    10
    15
    7

構造函數

構造函數是特殊類型的函數自動創建一(yī)個對象時函數的功能會自動執行。所以我(wǒ)們充分(fēn)利用這個行爲,通過構造函數初始化很多功能。PHP 提供了一(yī)個特殊的函數叫做 __construct()來定義一(yī)個構造函數。你可以把參數傳遞到構造函數中(zhōng)。以下(xià)示例将爲書(shū)籍類,在創建對象的時候它将創建一(yī)個構造函數用來初始化價格和标題這本書(shū)。

    function __construct( $par1, $par2 ){
       $this->price = $par1;
       $this->title = $par2;
    }

現在我(wǒ)們不需要調用設置好的函數分(fēn)别設置價格和标題。我(wǒ)們可以初始化這兩個成員(yuán)變量隻在創建對象的時候。檢查以下(xià)例子:

    $physics = new Books( "Physics for High School", 10 );
    $maths = new Books ( "Advanced Chemistry", 15 );
    $chemistry = new Books ("Algebra", 7 );

    /* Get those set values */
    $physics->getTitle();
    $chemistry->getTitle();
    $maths->getTitle();

    $physics->getPrice();
    $chemistry->getPrice();
    $maths->getPrice();

這将産生(shēng)以下(xià)結果:

    Physics for High School
    Advanced Chemistry
    Algebra
    10
    15
    7

析構函數

您可以定義析構函數:就像定義一(yī)個構造函數,析構函數使用函數__destruct()。你可以調用一(yī)個析構函數釋放(fàng)所有資(zī)源。

繼承

PHP 類定義可以使用 extends 關鍵字繼承一(yī)個父類。語法如下(xià):

    class Child extends Parent {
     <definition body>
    }

繼承的影響是子類 (或派生(shēng)類或子類)具有以下(xià)特點:

  • 自動繼承所有父類的成員(yuán)變量聲明。

  • 自動繼承父類的成員(yuán)函數。(默認情況下(xià))像父類一(yī)樣使用函數。以下(xià)例子書(shū)類繼承和基于需求增加了更多的功能。

    class Novel extends Books{
       var publisher;
       function setPublisher($par){
         $this->publisher = $par;
       }
       function getPublisher(){
         echo $this->publisher. "<br />";
       }
    }

現在除了繼承功能,類帶了兩個額外(wài)的成員(yuán)函數。

函數重載

函數定義子類覆蓋與父類中(zhōng)相同的屬性及方法名稱。在子類中(zhōng),我(wǒ)們可以修改繼承自父類中(zhōng)的方法。

在以下(xià)示例中(zhōng) getPrice 和 getTitle 方法重載。

    function getPrice(){
       echo $this->price . "<br/>";
       return $this->price;
    }
    function getTitle(){
       echo $this->title . "<br/>";
       return $this->title;
    }

公共成員(yuán)

除非你指定,否則類的屬性和方法默認都是公共的。也就是說,他們可能在三種可能的情況下(xià)被訪問:

  • 從類外(wài)聲明。

  • 在類中(zhōng)聲明。

  • 從另一(yī)個類中(zhōng)實現的類聲明它。

直到現在我(wǒ)們看到所有成員(yuán)都作爲公共成員(yuán)。如果你想限制類的成員(yuán)的可訪問性,然後你必須定義類成員(yuán)爲 private 或者 protected。

私有成員(yuán)

通過指定一(yī)個私有成員(yuán),你可以限制其訪問對象在類外(wài)訪問它。類的私有成員(yuán)不能在繼承類中(zhōng)調用它,也不能從類外(wài)部訪問。

私有屬性或方法隻能在本類内使用:

    class MyClass {
       private $car = "skoda";
       $driver = "SRK";

       function __construct($par) {
          // Statements here run every time
          // an instance of the class
          // is created.
       }
       function myPublicFunction() {
          return("I'm visible!");
       }
       private function myPrivateFunction() {
          return("I'm  not visible outside!");
       }
    }

當 MyClass 類被一(yī)個類使用關鍵字 extends 繼承時,myPublicFunction() 方法在子類中(zhōng)是可用的,屬性$drive也一(yī)樣。方法 myPrivateFunction() 和屬性 $car 在子類中(zhōng)是不可以被繼承的當然也不可以用,因爲他們被聲明爲了私有的。

受保護成員(yuán)

訪問一(yī)個受保護的屬性或方法并在類中(zhōng)聲明它,以及使用關鍵字 extends 繼承該類時。保護成員(yuán)在兩種類型的類之外(wài)無法使用。一(yī)個類成員(yuán)可以使用關鍵字 protected 在其前面。

這是不同版本的 MyClass 類:

    class MyClass {
       protected $car = "skoda";
       $driver = "SRK";

       function __construct($par) {
          // Statements here run every time
          // an instance of the class
          // is created.
       }
       function myPublicFunction() {
          return("I'm visible!");
       }
       protected function myPrivateFunction() {
          return("I'm  visible in child class!");
       }
    }

接口

接口被開(kāi)發人員(yuán)定義爲提供一(yī)個普通的方法名。不同的開(kāi)發人員(yuán)可以根據他們不同的需求來分(fēn)别實現這些接口。你可以說,接口是根據不同的需求被開(kāi)發人員(yuán)所實現。

PHP5,可以定義一(yī)個接口,如下(xià):

    interface Mail {
       public function sendMail();
    }

然後,另一(yī)個類像這樣實現該接口:

    class Report implements Mail {
       // sendMail() Definition goes here
    }

常量

一(yī)個常量有點像一(yī)個變量,它擁有一(yī)個值,但實際上更像一(yī)個函數,因爲常量是永遠不變的。一(yī)旦你聲明一(yī)個常量,它不能被改變。

聲明一(yī)個常量是很容易的,就像下(xià)面這個版本的 MyClass,它完成了常量的定義:

    class MyClass {
       const requiredMargin = 1.7;
       function __construct($incomingValue) {
          // Statements here run every time
          // an instance of the class
          // is created.
       }
    }

在這個類中(zhōng),requiredMargin 是一(yī)個常量。它是用關鍵字 const 聲明常量,在任何情況不可以改變他的值 1.7。注意,常量的定義沒有 $ 符号,不能像變量那樣。

抽象類

抽象類不能被實例化,隻能被繼承。你用關鍵字 abstract 聲明一(yī)個抽象類,就像這樣:

當繼承一(yī)個抽象類的時候,子類必須實現抽象類中(zhōng)的所有的抽象方法,另外(wài),這些方法的可見性必須和抽象類中(zhōng)一(yī)樣(或更輕松)。

    abstract class MyAbstractClass {
       abstract function myAbstractFunction() {
       }
    }

注意,方法定義在一(yī)個抽象類中(zhōng)在方法名稱前面之前必須使用關鍵字 abstract。抽象方法定義在一(yī)個非抽象類中(zhōng)是不合法的。

Static關鍵字

聲明類屬性或方法爲靜态,就可以不實例化類而直接訪問。靜态屬性不能通過一(yī)個類已實例化的對象來訪問(但靜态方法可以)。

試運行下(xià)面的例子:

    <?php
    class Foo
    {
        public static $my_static = 'foo';

        public function staticValue() {
            return self::$my_static;
        }
    }
    print Foo::$my_static . "\n";
    $foo = new Foo();
    print $foo->staticValue() . "\n";

final 關鍵字

PHP 5 介紹了這個 final 關鍵字。如果父類中(zhōng)的方法被聲明爲 final,則子類無法覆蓋該方法。如果一(yī)個類被聲明爲 final,則不能被繼承。

以下(xià)的例子會産生(shēng)一(yī)個緻命錯誤:Cannot override final method BaseClass::moreTesting()。

    <?php
    class BaseClass {
       public function test() {
           echo "BaseClass::test() called<br>";
       }

       final public function moreTesting() {
           echo "BaseClass::moreTesting() called<br>";
       }
    }

    class ChildClass extends BaseClass {
       public function moreTesting() {
           echo "ChildClass::moreTesting() called<br>";
       }
    }
    ?>

調用父類的構造函數

當子類需要一(yī)個構造函數時,需要調用父類的構造函數而不是在子類中(zhōng)寫一(yī)個全新的構造函數,我(wǒ)們需要調用父類的構造函數加一(yī)下(xià)我(wǒ)們要寫的内容,另外(wài)在子類的構造函數中(zhōng)做一(yī)些初始化是必要的。這是一(yī)個簡單的例子:

    class Name
    {
       var $_firstName;
       var $_lastName;
       function Name($first_name, $last_name)
       {
         $this->_firstName = $first_name;
         $this->_lastName = $last_name;
       }
       function toString() {
         return($this->_lastName .", " .$this->_firstName);
       }
    }
    class NameSub1 extends Name
    {
       var $_middleInitial;
       function NameSub1($first_name, $middle_initial, $last_name) {
           Name::Name($first_name, $last_name);
           $this->_middleInitial = $middle_initial;
       }
       function toString() {
           return(Name::toString() . " " . $this->_middleInitial);
       }
    }

在上面這個例子中(zhōng),我(wǒ)們有一(yī)個父類(Name),它裏面有一(yī)個二個參數的構造函數,在子類中(zhōng)(NameSub1)有一(yī)個帶有 3 個參數的構造函數。子類 NameSub1 中(zhōng)的構造函數通過調用其父類中(zhōng)的構造函數 Name::Name(傳遞兩個參數)加以使用,然後增加一(yī)個額外(wài)的屬性。同樣,NameSub1 定義了 toString() 方法然後重寫父類中(zhōng)的 toString() 方法。

注:上例中(zhōng)定義的,可以在子類中(zhōng)定義和父類中(zhōng)相同的構造函數,并且名字名稱相同。

相關内容