php物件導向編程(二),php物件導向編程_PHP教程

來源:互聯網
上載者:User

php物件導向編程(二),php物件導向編程


現在我們來瞭解一下物件導向的一個封裝性的問題

封裝性:在我的理解裡面 可以理解為一個u盤 我們使用u盤的介面與電腦進行資料之間的互動 但是我們不能看到裡面的結構 這個特性我們可以稱為封裝性

好處:利用這個特性我們可以最大程度的提高代碼的品質 我們在其他代碼中只要對介面進行引用不用每次都寫 提高代碼的自量 以及減少排除bug的難度

現在我們來思考個問題:個人電腦都有一個密碼,不想讓其它人隨意的登陸,在你電腦裡面拷貝和粘貼。還有就是像人這個對象, 身高和年齡的屬性, 只能是自己來增漲,不可以讓別人隨意的賦值等等。

我們使用private這個關鍵詞對代碼進行封裝

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

  注意:只要成員屬性前面有其他的關鍵字,那麼就要去掉var

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

  

輸出結果為:

Fatal error: Cannot access private property Person::$name
Fatal error: Cannot access private property Person::$sex
Fatal error: Cannot access private property Person::$age
Fatal error: Cannot access private property Person::$name
Fatal error: Call to private method Person::run() from context ' '
沒有加任何存取控制,預設的是public的,任何地方都可以訪問。

// 這個人可以說話的方法, 說出自己的私人屬性,在這裡也可以訪問私人方法function say(){echo "我的名子叫:" . $this->name . " 性別:" . $this->sex . " 我的年齡是:" . $this->age;// 在這裡也可以訪問私人方法//$this->run();}

  因為成員方法say()是公有的, 所以我們在類的外部調用say()方法是可以的,改變上面的代碼:

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;}}// 通過構造方法建立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();?>

  因為構造方法是預設的公有方法(構造方法不要設定成私人的),如果設定稱為私人的話,就等同將u盤中的唯一一個介面封死,我們就不能對這個類進行訪問

上面的例子中我們可以看到, 私人的成員只能在類的內部使用, 不能被類外部直接來存取 但是我們有時候有需要對私人屬性進行賦值和讀取,我們需要給類的外部提供一些可以存取的介面。

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

  下面我們要瞭解一下__set,__get,__isset,__unset四個方法的應用

經過上面的講解可能會有疑問 那麼我們如何對私人類進行操作呢?????

__set設定:__get

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

  一個完整的樣本:

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

  

程式執行結果:

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

以上代碼如果不加上__get()和__set()方法,程式就會出錯,因為不能在類的外部操作私人成員,而上面的代碼是通過自動調用__get()和__set()方法來協助我們直接存取封裝的私人成員的。

如果在一個對象外面使用“isset()”這個函數去測定對象裡面的成員是否被設定可不可以用它呢?分兩種情況,如果對象裡面成員是公有的,我們就可以使用這個函數來測定成員屬性,如果是私人的成員屬性,這個函數就不起作用了,原因就是因為私人的被封裝了,在外部不可見。那麼我們就不可以在對象的外部使用“isset()”函數來測定私人成員屬性是否被設定了呢?可以,你只要在類裡面加上一個“__isset()”方法就可以了,當在類外部使用”isset()”函數來測定對象裡面的私人成員是否被設定時,就會自動調用類裡面的“__isset()”方法了幫我們完成這樣的操作,“__isset()”方法也可以做成私人的。你可以在類裡面加上下面這樣的代碼就可以了:

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

完整例子

$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()函數測定私人成員時,自動調用
";return isset($this->$nm);}//__unset()方法private function __unset($nm){echo "當在類外部使用unset()函數來刪除私人成員時自動調用的
";unset($this->$nm);}}$p1 = new Person();$p1->name = "this is a person name";// 在使用isset()函數測定私人成員時,自動調用__isset()方法幫我們完成,返回結果為trueecho var_dump(isset($p1->name)) . "
";echo $p1->name . "
";// 在使用unset()函數刪除私人成員時,自動調用__unset()方法幫我們完成,刪除name私人屬性unset($p1->name);// 已經被刪除了,所這行不會有輸出echo $p1->name;?>

  

輸出結果為:

isset()函數測定私人成員時,自動調用
boolean true
this is a person name
當在類外部使用unset()函數來刪除私人成員時自動調用的
isset()函數測定私人成員時,自動調用

  下面我們要來瞭解的是繼承的知識

下面是人類的代碼

// 定義一個“人”類做為父類class Person{// 下面是人的成員屬性var $name;//人的名子var $sex;//人的性別var $age;//人的年齡// 定義一個構造方法參數為屬性姓名$name、性別$sex和年齡$age進行賦值function __construct($name, $sex, $age) {$this->name = $name;$this->sex = $sex;$this->age = $age;}// 這個人可以說話的方法, 說出自己的屬性function say() {echo "我的名子叫:" . $this->name . " 性別:" . $this->sex . " 我的年齡是:" . $this->age;}}

  下面是學生類的代碼

class Student{// 下面是人的成員屬性var $name;// 人的名字var $sex;// 人的性別var $age;// 人的年齡var $school;// 學生所在學校的屬性// 定義一個構造方法參數為屬性姓名$name、性別$sex 和年齡$age 進行賦值function __construct($name = "", $sex = "", $age = "", $school = ""){$this->name = $name;$this->sex = $sex;$this->age = $age;$this->school = $school;}// 這個人可以說話的方法, 說出自己的屬性function say() {echo "我的名字叫:" . $this->name . " 性別:" . $this->sex . " 我的年齡是:" . $this->age . "
";}// 這個學生學習的方法function study() {echo "我的名字叫:" . $this->name . " 我正在" . $this->school . "學習
";}}

  對學生類進行簡化

class Student extends Person{var $school;// 學生所在學校的屬性// 這個學生學習的方法function study(){echo "我的名字叫:" . $this->name . " 我正在" . $this->school . "學習
";}}

  現在我們要考慮的是重載的問題

這個時候你可能會有疑問 php 好像是不能重載的,因為PHP是一門若語言的,傳統意義上的重載是有多個的方法名相同的方法,但是帶有不同個數的參,我們利用參數的不同調用不同的介面

 我所說的重載是子類對父類的一個覆蓋

name = $name;$this->sex = $sex;$this->age = $age;}// 這個人可以說話的方法, 說出自己的屬性function say(){echo "我的名子叫:" . $this->name . " 性別:" . $this->sex . " 我的年齡是:" . $this->age;}}class Student extends Person{var $school; // 學生所在學校的屬性// 這個學生學習的方法function study(){echo "我的名子叫:" . $this->name . " 我正在" . $this->school . " 學習";}// 這個學性可以說話的方法, 說出自己所有的屬性,覆蓋了父類的同名方法function say(){echo "我的名子叫:" . $this->name . " 性別:" . $this->sex . " 我的年齡是:" . $this->age . " 我在" . $this->school . "上學";}}?>

  這樣就能實現了 這種方法歸根到底是的要點是:

1。子類要對父類繼承

2.子類的方法名要與父類的方法名相同

這個時候我們可能發現如果這個方法中有1000條代碼那麼 實現起來很不方便

此時我們,使用“parent::方法名”的方試來調用父類中被覆蓋的方法;

class Student extends Person{var $school;// 學生所在學校的屬性// 這個學生學習的方法function study() {echo "我的名子叫:" . $this->name . " 我正在" . $this->school . "學習";}// 這個學性可以說話的方法, 說出自己所有的屬性,覆蓋了父類的同名方法function say() {// 使用父類的"類名::"來調用父類中被覆蓋的方法;// Person::say();// 或者使用"parent::"的方試來調用父類中被覆蓋的方法;parent::say();// 加上一點自己的功能echo "我的年齡是:" . $this->age . " 我在" . $this->school . "上學";}}

  對public,private,protected的區別

MyPublic();$this->MyProtected();$this->MyPrivate();}}$myclass = new MyClass;$myclass->MyPublic();// Works$myclass->MyProtected();// Fatal Error$myclass->MyPrivate();// Fatal Error$myclass->Foo();// Public, Protected and Private work/** * Define MyClass2 */class MyClass2 extends MyClass{// This is publicfunction Foo2(){$this->MyPublic();$this->MyProtected();$this->MyPrivate();// Fatal Error}}$myclass2 = new MyClass2;$myclass2->MyPublic();// Works$myclass2->Foo2();// Public and Protected work, not Private?>

  從上面的代碼我們可以總結如下

public:可以直接進行外部存取

protected 間接的外部存取 像隨身碟和電腦一樣 訪問需要一個介面 而那個介面就是需要一個子類 (子類繼承了父類的protected)

private 不能通過外部存取

既然談到繼承的問題 如果我們想要一個類不被繼承那麼我們可以用final 去進行定義(只能定義類和方法,不能定義成員屬性)

1.final 標記的類不能被繼承

2.final標記的方法不能被子類覆蓋


  

會出現下面錯誤:

Fatal error: Class Student may not inherit from final class (Person)

  理解static 和const的關鍵關鍵字的使用(self:)

static 字面上的意思就是靜態意思 現在你可能會問靜態使用靜態有什麼好處?使用靜態好處是:如果樣本話成千上萬“人”的對象,裡面都有一個共有的屬性比如國籍“中國”,那麼我們可以建國籍這個屬性設定為靜態,在記憶體在開闢出一個位置,執行個體化的過程中成千上萬的人都會訪問記憶體中這個位置

static成員能夠限制外部的訪問,因為static的成員是屬於類的,是不屬於任何對象執行個體,是在類第一次被載入的時候分配的空間,其他類是無法訪問的,只對類的執行個體共用,能一定程度對類該成員形成保護;

這一點有點像網站中的全域變數


  結果是:

中國我是中國人美國

也可以這麼寫

showConstant();// echo $class::constant; // 是不允許的?>

  用“const”修飾的成員屬性的訪問方式和“static”修飾的成員訪問的方式差不多,也是使用“類名”,在方法裡面使用“self”關鍵字。但是不用使用“$”符號,也不能使用對象來訪問。

showConstant();// echo $class::constant; // 是不允許的?>

  

http://www.bkjia.com/PHPjc/1101501.htmlwww.bkjia.comtruehttp://www.bkjia.com/PHPjc/1101501.htmlTechArticlephp物件導向編程(二),php物件導向編程 現在我們來瞭解一下物件導向的一個封裝性的問題 封裝性:在我的理解裡面 可以理解為一個u盤 我們...

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.