屬性(Properties)

2018-02-24 15:40 更新

屬性(Property)

在 PHP 中,類的成員變量也被稱為屬性(properties)。它們是類定義的一部分,用來(lái)表現(xiàn)一個(gè)實(shí)例的狀態(tài)(也就是區(qū)分類的不同實(shí)例)。在具體實(shí)踐中,常常會(huì)想用一個(gè)稍微特殊些的方法實(shí)現(xiàn)屬性的讀寫。例如,如果有需求每次都要對(duì)?label?屬性執(zhí)行 trim 操作,就可以用以下代碼實(shí)現(xiàn):

$object->label = trim($label);

上述代碼的缺點(diǎn)是只要修改?label?屬性就必須再次調(diào)用?trim()?函數(shù)。若將來(lái)需要用其它方式處理?label?屬性,比如首字母大寫,就不得不修改所有給?label?屬性賦值的代碼。這種代碼的重復(fù)會(huì)導(dǎo)致 bug,這種實(shí)踐顯然需要盡可能避免。

為解決該問(wèn)題,Yii 引入了一個(gè)名為 yii\base\Object 的基類,它支持基于類內(nèi)的?getter?和?setter(讀取器和設(shè)定器)方法來(lái)定義屬性。如果某類需要支持這個(gè)特性,只需要繼承 yii\base\Object 或其子類即可。

補(bǔ)充:幾乎每個(gè) Yii 框架的核心類都繼承自 yii\base\Object 或其子類。這意味著只要在核心類中見(jiàn)到 getter 或 setter 方法,就可以像調(diào)用屬性一樣調(diào)用它。

getter 方法是名稱以?get?開頭的方法,而 setter 方法名以?set?開頭。方法名中?get?或?set?后面的部分就定義了該屬性的名字。如下面代碼所示,getter 方法?getLabel()?和 setter 方法?setLabel()?操作的是?label?屬性,:

namespace app\components;

use yii\base\Object;

class Foo extend Object
{
    private $_label;

    public function getLabel()
    {
        return $this->_label;
    }

    public function setLabel($value)
    {
        $this->_label = trim($value);
    }
}

(詳細(xì)解釋:getter 和 setter 方法創(chuàng)建了一個(gè)名為?label?的屬性,在這個(gè)例子里,它指向一個(gè)私有的內(nèi)部屬性?_label。)

getter/setter 定義的屬性用法與類成員變量一樣。兩者主要的區(qū)別是:當(dāng)這種屬性被讀取時(shí),對(duì)應(yīng)的 getter 方法將被調(diào)用;而當(dāng)屬性被賦值時(shí),對(duì)應(yīng)的 setter 方法就調(diào)用。如:

// 等效于 $label = $object->getLabel();
$label = $object->label;

// 等效于 $object->setLabel('abc');
$object->label = 'abc';

只定義了 getter 沒(méi)有 setter 的屬性是只讀屬性。嘗試賦值給這樣的屬性將導(dǎo)致 yii\base\InvalidCallException (無(wú)效調(diào)用)異常。類似的,只有 setter 方法而沒(méi)有 getter 方法定義的屬性是只寫屬性,嘗試讀取這種屬性也會(huì)觸發(fā)異常。使用只寫屬性的情況幾乎沒(méi)有。

通過(guò) getter 和 setter 定義的屬性也有一些特殊規(guī)則和限制:

  • 這類屬性的名字是不區(qū)分大小寫的。如,$object->label?和?$object->Label?是同一個(gè)屬性。因?yàn)?PHP 方法名是不區(qū)分大小寫的。
  • 如果此類屬性名和類成員變量相同,以后者為準(zhǔn)。例如,假設(shè)以上?Foo?類有個(gè)?label?成員變量,然后給?$object->label = 'abc'?賦值,將賦給成員變量而不是 setter?setLabel()?方法。
  • 這類屬性不支持可見(jiàn)性(訪問(wèn)限制)。定義屬性的 getter 和 setter 方法是 public、protected 還是 private 對(duì)屬性的可見(jiàn)性沒(méi)有任何影響。
  • 這類屬性的 getter 和 setter 方法只能定義為非靜態(tài)的,若定義為靜態(tài)方法(static)則不會(huì)以相同方式處理。

回到開頭提到的問(wèn)題,與其處處要調(diào)用?trim()?函數(shù),現(xiàn)在我們只需在 setter?setLabel()?方法內(nèi)調(diào)用一次。如果 label 首字母變成大寫的新要求來(lái)了,我們只需要修改setLabel()?方法,而無(wú)須接觸任何其它代碼。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)