php物件導向學習教程5

來源:互聯網
上載者:User
9.封裝性
封裝性是物件導向編程中的三大特性之一,封裝性就是把對象的屬性和服務結合成一個獨立的
相同單位,並儘可能隱蔽對象的內部細節,包含兩個含義:1.把對象的全部屬性和全部服務結合在一
起,形成一個不可分割的獨立單位(即對象)。2.資訊隱蔽,即儘可能隱蔽對象的內部細節,對外形
成一個邊界〔或者說形成一道屏障〕,只保留有限的對外介面使之與外部發生聯絡。
封裝的原則在軟體上的反映是:要求使對象以外的部分不能隨意存取對象的內部資料(屬性),
從而有效避免了外部錯誤對它的"交叉感染",使軟體錯誤能夠局部化,大大減少查錯和排錯的難
度。
用個執行個體來說明吧,假如某個人的對象中有年齡和工資等屬性,像這樣個人隱私的屬性是不想
讓其它人隨意就能獲得到的,如果你不使用封裝,那麼別人想知道就能得到,但是如果你封裝上之
後別人就沒有辦法獲得封裝的屬性,除非你自己把它說出去,否則別人沒有辦法得到。
再比如說,個人電腦都有一個密碼,不想讓其它人隨意的登陸,在你的電腦裡面拷貝和粘貼。
還有就是像人這個對象,身高和年齡的屬性,只能是自己來增長,不可以讓別人隨意的賦值等等。
使用private 這個關鍵字來對屬性和方法進行封裝:
原來的成員:

var $name; //聲明人的姓名var $sex; //聲明人的性別var $age; //聲明人的年齡function run(){… … .}

改成封裝的形式:

private $name; //把人的姓名使用private 關鍵字進行封裝private $sex; //把人的性別使用private 關鍵字進行封裝private $age; //把人的年齡使用private 關鍵字進行封裝private function run(){… … } //把人的走路方法使用private 關鍵字進行封裝

注意:只要是成員屬性前面有其它的關鍵字就要去掉原有的關鍵字“var”。
通過private 就可以把人的成員(成員屬性和成員方法)封裝上了。封裝上的成員就不能被類外
面直接存取了,只有對象內部自己可以訪問;下面的代碼會產生錯誤:

class Person{//下面是人的成員屬性private $name; //人的名字,被private封裝上了private $sex; //人的性別, 被private封裝上了private $age; //人的年齡, 被private封裝上了//這個人可以說話的方法function say(){echo "我的名字叫:".$this->name." 性別:".$this->sex." 我的年齡是:".$this->age."<br>";}//這個人可以走路的方法, 被private封裝上了private function run(){echo "這個人在走路";}}//執行個體化一個人的執行個體對象$p1=new Person();//試圖去給私人的屬性賦值, 結果會發生錯誤$p1->name="張三";$p1->sex="男";$p1->age=20;//試圖去列印私人的屬性, 結果會發生錯誤echo $p1->name.”<br>”;echo $p1->sex.”<br>”;echo $p1->age.”<br>”//試圖去列印私人的成員方法, 結果會發生錯誤$p1->run();

輸出結果為:

Fatal error: Cannot access private property Person::$nameFatal error: Cannot access private property Person::$sexFatal error: Cannot access private property Person::$ageFatal error: Cannot access private property Person::$nameFatal error: Call to private method Person::run() from context ''

從上面的執行個體可以看到,私人的成員是不能被外部存取的,因為私人成員只能在本對象內部自
己訪問,比如,$p1 這個對象自己想把他的私人屬性說出去,在say()這個方法裡面訪問了私人屬性,
這樣是可以。(沒有加任何存取控制,預設的是public 的,任何地方都可以訪問)

//這個人可以說話的方法, 說出自己的私人屬性,在這裡也可以訪問私人方法function say(){echo "我的名字叫:".$this->name." 性別:".$this->sex." 我的年齡是:".$this->age."<br>";//在這裡也可以訪問私人方法//$this->run();}因為成員方法say()是公有的, 所以我們在類的外部調用say()方法是可以的,改變上面的代碼;class Person{//下面是人的成員屬性private $name; //人的名字,被private封裝上了private $sex; //人的性別, 被private封裝上了private $age; //人的年齡, 被private封裝上了//定義一個構造方法參數為私人的屬性姓名$name、性別$sex和年齡$age進行賦值function __construct($name, $sex, $age){//通過構造方法傳進來的$name給私人成員屬性$this->name賦初使值$this->name=$name;//通過構造方法傳進來的$sex給私人成員屬性$this->sex賦初使值$this->sex=$sex;//通過構造方法傳進來的$age給私人成員屬性$this->age賦初使值$this->age=$age;}//這個人可以說話的方法, 說出自己的私人屬性,在這裡也可以訪問私人方法function say(){echo "我的名字叫:".$this->name." 性別:".$this->sex." 我的年齡是:".$this->age."<br>";}}//通過構造方法建立3個對象$p1、p2、$p3,分別傳入三個不同的實參為姓名、性別和年齡$p1=new Person(“張三”,”男”, 20);$p2=new Person(“李四”,”女”, 30);$p3=new Person(“王五”,”男”, 40);//下面訪問$p1對象中的說話方法$p1->say();//下面訪問$p2對象中的說話方法$p2->say();//下面訪問$p3對象中的說話方法$p3->say();

輸出結果為:

我的名字叫:張三性別:男我的年齡是:20我的名字叫:李四性別:女我的年齡是:30我的名字叫:王五性別:男我的年齡是:40

因為構造方法是預設的公有方法(構造方法不要設定成私人的),所以在類的外面可以訪問到,
這樣就可以使用構造方法建立對象, 另外構造方法也是類裡面的函數,所以可以用構造方法給私
有的屬性賦初值。Say()的方法是預設公有的, 所以在外面也可以訪問的到, 說出他自己的私人屬
性。
從上面的例子中我們可以看到,私人的成員只能在類的內部使用,不能被類外部直接來存取,
但是在類的內部是有許可權訪問的,所以有時候我們需要在類的外面給私人屬性賦值和讀取出來,也
就是給類的外部提供一些可以存取的介面,上例中構造方法就是一種賦值的形式,但是構造方法只
是在建立對象的時候賦值,如果我們已經有一個存在的對象了,想對這個存在的對象賦值,這個時
候,如果你還使用構造方法傳值的形式傳值,那麼就建立了一個新的對象,並不是這個已存在的對
象了。所以我們要對私人的屬性做一些可以被外部存取的介面,目的就是可以在對象存在的情況下,
改變和存取屬性的值,但要注意,只有需要讓外部改變的屬性才這樣做,不想讓外面訪問的屬性是
不做這樣的介面的,這樣就能達到封裝的目的,所有的功能都是對象自己來完成,給外面提供盡量
少的操作。
如果給類外部提供介面,可以為私人屬性在類外部提供設定方法和擷取方法,來操作私人屬性.
例如:

prvate $age; //私人的屬性年齡function setAge($age) //為外部提供一個公有設定年齡的方法{if($age<0 || $age>130) //在給屬性賦值的時候,為了避免非法值設定給屬性return;$this->age=$age;}function getAge() //為外部提供一個公有擷取年齡的方法{return($this->age);}

上面的方法是為一個成員屬性設定和擷取值, 當然你也可以為每個屬性用同樣的方法對其進行
賦值和取值的操作,完成在類外部的存取工作。
10.__set() __get() __isset() __unset()四個方法的應用
一般來說,總是把類的屬性定義為private,這更符合現實的邏輯。但是,對屬性的讀取和賦值
操作是非常頻繁的,因此在PHP5 中,預定義了兩個函數“__get()”和“__set()”來擷取和賦值其
屬性,以及檢查屬性的“__isset()”和刪除屬性的方法“__unset()”。
上一節中,我們為每個屬性做了設定和擷取的方法,在PHP5 中給我們提供了專門為屬性設定
值和擷取值的方法,“__set()”和“__get()”這兩個方法,這兩個方法不是預設存在的,而是我們手
工添加到類裡面去的,像構造方法(__construct())一樣, 類裡面添加了才會存在,可以按下面的方式
來添加這兩個方法,當然也可以按個人的風格來添加:
//__get()方法用來擷取私人屬性

private function __get($property_name){if(isset($this->$property_name)){return($this->$property_name);}else{return(NULL);}}//__set()方法用來設定私人屬性private function __set($property_name, $value){$this->$property_name = $value;}

__get()方法:

這個方法用來擷取私人成員屬性值的,有一個參數,參數傳入你要擷取的成員屬性
的名稱,返回擷取的屬性值,這個方法不用我們手工的去調用,因為我們也可以把這個方法做成私
有的方法,是在直接擷取私人屬性的時候對象自動調用的。因為私人屬性已經被封裝上了,是不能
直接擷取值的(比如:“echo $p1->name”這樣直接擷取是錯誤的),但是如果你在類裡面加上了這
個方法,在使用“echo $p1->name”這樣的語句直接擷取值的時候就會自動調用__get($property_name)
方法,將屬性name 傳給參數$property_name,通過這個方法的內部執行,返回我們傳入的私人屬性
的值。如果成員屬性不封裝成私人的,對象本身就不會去自動調用這個方法。
__set()方法:這個方法用來為私人成員屬性設定值的,有兩個參數,第一個參數為你要為設定
值的屬性名稱,第二個參數是要給屬性設定的值,沒有傳回值。這個方法同樣不用我們手工去調用,
它也可以做成私人的,是在直接設定私人屬性值的時候自動調用的,同樣屬性私人的已經被封裝上
了, 如果沒有__set()這個方法,是不允許的, 比如:$this->name=‘zhangsan’, 這樣會出錯,但
是如果你在類裡面加上了__set($property_name, $value)這個方法,在直接給私人屬性賦值的時候,
就會自動調用它,把屬性比如name 傳給$property_name, 把要賦的值“zhangsan”傳給$value,通過
這個方法的執行,達到賦值的目的。如果成員屬性不封裝成私人的,對象本身就不會去自動調用這
個方法。為了不傳入非法的值, 還可以在這個方法給做一下判斷。代碼如下:

<?phpclass Person{//下面是人的成員屬性, 都是封裝的私人成員private $name; //人的名字private $sex; //人的性別private $age; //人的年齡//__get()方法用來擷取私人屬性private function __get($property_name){echo "在直接擷取私人屬性值的時候,自動調用了這個__get()方法<br>";if(isset($this->$property_name)){return($this->$property_name);}else{return(NULL);}}//__set()方法用來設定私人屬性private function __set($property_name, $value){echo "在直接設定私人屬性值的時候,自動調用了這個__set()方法為私人屬性賦值<br>";$this->$property_name = $value;}}$p1=new Person();//直接為私人屬性賦值的操作, 會自動調用__set()方法進行賦值$p1->name="張三";$p1->sex="男";$p1->age=20;//直接擷取私人屬性的值, 會自動調用__get()方法,返回成員屬性的值echo "姓名:".$p1->name."<br>";echo "性別:".$p1->sex."<br>";echo "年齡:".$p1->age."<br>";?>

程式執行結果:

在直接設定私人屬性值的時候,自動調用了這個__set()方法為私人屬性賦值在直接設定私人屬性值的時候,自動調用了這個__set()方法為私人屬性賦值在直接設定私人屬性值的時候,自動調用了這個__set()方法為私人屬性賦值在直接擷取私人屬性值的時候,自動調用了這個__get()方法姓名:張三在直接擷取私人屬性值的時候,自動調用了這個__get()方法性別:男在直接擷取私人屬性值的時候,自動調用了這個__get()方法年齡:20

以上代碼如果不加上__get()和__set()方法,程式就會出錯,因為不能在類的外部操作私人成員,
而上面的代碼是通過自動調用__get()和__set()方法來協助我們直接存取封裝的私人成員的。
__isset() 方法:在看這個方法之前我們看一下“isset()”函數的應用,isset()是測定變數是否設
定用的函數,傳入一個變數作為參數,如果傳入的變數存在則傳回true,否則傳回false。那麼如果
在一個對象外面使用“isset()”這個函數去測定對象裡面的成員是否被設定可不可以用它呢?分兩種
情況,如果對象裡面成員是公有的,我們就可以使用這個函數來測定成員屬性,如果是私人的成員
屬性,這個函數就不起作用了,原因就是因為私人的被封裝了,在外部不可見。那麼我們就不可以
在對象的外部使用“isset()”函數來測定私人成員屬性是否被設定了呢?可以,你只要在類裡面加上
一個“__isset()”方法就可以了,當在類外部使用”isset()”函數來測定對象裡面的私人成員是否被設
定時, 就會自動調用類裡面的“__isset()”方法了幫我們完成這樣的操作,“__isset()”方法也可以
做成私人的。你可以在類裡面加上下面這樣的代碼就可以了:

private function __isset($nm){echo "當在類外部使用isset()函數測定私人成員$nm時,自動調用<br>";return isset($this->$nm);}

__unset()方法:

看這個方法之前呢,我們也先來看一下“unset()”這個函數,“unset()”這個函
數的作用是刪除指定的變數且傳回true,參數為要刪除的變數。那麼如果在一個對象外部去刪除對
象內部的成員屬性用“unset()”函數可不可以呢,也是分兩種情況,如果一個對象裡面的成員屬性
是公有的,就可以使用這個函數在對象外面刪除對象的公有屬性,如果對象的成員屬性是私人的,
我使用這個函數就沒有許可權去刪除,但同樣如果你在一個對象裡面加上“__unset()”這個方法,就
可以在對象的外部去刪除對象的私人成員屬性了。在對象裡面加上了“__unset()”這個方法之後,
在對象外部使用“unset()”函數刪除對象內部的私人成員屬性時,自動調用“__unset()”函數來幫
我們刪除對象內部的私人成員屬性,這個方法也可以在類的內部定義成私人的。在對象裡面加上下
面的代碼就可以了:

private function __unset($nm){echo "當在類外部使用unset()函數來刪除私人成員時自動調用的<br>";unset($this->$nm);}我們來看一個完整的執行個體:<?phpclass Person{//下面是人的成員屬性private $name; //人的名字private $sex; //人的性別private $age; //人的年齡//__get()方法用來擷取私人屬性private function __get($property_name){if(isset($this->$property_name)){return($this->$property_name);}else {return(NULL);}}//__set()方法用來設定私人屬性private function __set($property_name, $value){$this->$property_name = $value;}//__isset()方法private function __isset($nm){echo "isset()函數測定私人成員時,自動調用<br>";return isset($this->$nm);}//__unset()方法private function __unset($nm){echo "當在類外部使用unset()函數來刪除私人成員時自動調用的<br>";unset($this->$nm);}}$p1=new Person();$p1->name="this is a person name";//在使用isset()函數測定私人成員時,自動調用__isset()方法幫我們完成,返回結果為trueecho var_dump(isset($p1->name))."<br>";echo $p1->name."<br>";//在使用unset()函數刪除私人成員時,自動調用__unset()方法幫我們完成,刪除name私人屬性unset($p1->name);//已經被刪除了, 所這行不會有輸出echo $p1->name;?>

輸出結果為:

isset()函數測定私人成員時,自動調用bool(true)this is a person name當在類外部使用unset()函數來刪除私人成員時自動調用的__set()、__get()、__isset()、__unset() 這四個方法都是我們添加到對象裡面的,在需要時自動調用的,來完成在對象外部對對象內部私人屬性的操作

以上就是php物件導向學習教程5的內容,更多相關內容請關注topic.alibabacloud.com(www.php.cn)!

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.