在PHP中,多態性是指同一個操作作用於不同的類別的實例,將產生不同的執行結果。也即不同類別的對象收到相同的訊息時,將得到不同的結果;不同的對象,收到同一訊息將可以產生不同的結果,這種現象稱為多態性。多態性允許每個物件以適合自身的方式去回應共同的訊息;多態性增強了軟體的靈活性和重用性。
本教學操作環境:windows7系統、PHP8版、DELL G3電腦
多態性是指相同的操作或函數、過程可作用於多種類型的物件上並獲得不同的結果。不同的對象,收到相同訊息將可以產生不同的結果,這種現象稱為多態性。
多態性允許每個物件以適合自身的方式去回應共同的訊息。多態性增強了軟體的靈活性和重用性。
在物件導向的軟體開發中,多態性是最重要的部分之一。物件導向程式設計並非只是將相關的方法與資料簡單的結合起來,而是採用物件導向程式設計中的各種要素將現實生活中的各種情境清晰的描述出來。這一小節將對物件導向程式設計中的多態性作詳細的講解。
1.什麼是多態
多 態(Polymorphism)以字面上理解就是「多種形狀」。可以理解為多種表現形式,也即「一個對外接口,多個內部實作方法」。在物件導向的理論 中,多態性的一般定義為:同一個操作作用於不同的類別的實例,將產生不同的執行結果。也即不同類別的物件收到相同的訊息時,將會得到不同的結果。
在實際的應用開發中,採用物件導向中的多型主要在於可以將不同的子類別物件當作一個父類別來處理,並且可以屏蔽不同子類別物件之間所存在的差異,寫出通用的程式碼,做出通用的編程,以適應需求的不斷變化。
2. 多型態的應用設計
在實際的應用開發中,通常為了讓專案能夠在以後的時間裡的輕鬆實現擴展與升級,需要透過繼承實現可重複使用模組進行輕鬆升級。在進行可重複使用模組設計時,就需要盡可能減少的使用流程控制語句。此時就可以採用多型實作該類別設計。
【範例】例舉了通常採用流程控制語句實現不同類別的處理。其程式碼如下所示。
class painter{ //定义油漆工类 public function paintbrush(){ //定义油漆工动作 echo "油漆工正在刷漆!\n"; } } class typist{ //定义打字员类 public function typed(){ //定义打字员工作 echo "打字员正在打字!\n"; } } function printworking($obj){ //定义处理类 if(objinstanceofpainter)//若对象是油漆工类,则显示油漆工动作$obj−>paintbrush();elseif(obj instanceof typist){ //若对象是打字员类,则显示打字员动作 $obj->typed(); }else{ //若非以上类,则显示出错信息 echo "Error: 对象错误!"; } } printworking(new painter()); //显示员工工作 printworking(new typist()); //显示员工工作
分析:在上述程序中,首先定義兩個員工類別:油漆工類別和打字員類別。然後定義一個處理函數,在該函數中,判斷員工是否為已經定義的員工,並列印出員工的工作狀態。其結果如下所示。
油漆工正在刷漆 打字员正在打字
從以上程式可輕鬆看出,若想顯示其幾種員工的工作狀態,需要先定義該員工類,並在該員工類中定義員工的工作,然後在printworking()函數中增加elseif語句以檢查物件是哪一員工類別的實例。這在實際的應用中,是非常不可取的。若此時採用多態,則可輕鬆解決此問題。
可以先建立一個員工父類,所有的員工類別都會繼承自該員工父類,並且繼承父類別的所有方法與屬性。然後在員工類別中建立「是一」關係,判斷是否為合法的員工。
【範例】例舉了採用多型態的方式改寫上例。其程式碼如下所示。
class employee{//定义员工父类 protected function working(){//定义员工工作,需要在子类的实现 echo "本方法需要在子类中重载!"; } } class painter extends employee{//定义油漆工类 public function working(){//实现继承的工作方法 echo "油漆工正在刷漆!\n"; } } class typist extends employee{//定义打字员类 public function working(){ echo "打字员正在打字!\n"; } } class manager extends employee{//定义经理类 public function working(){ echo "经理正在开会!"; } } function printworking($obj){//定义处理方法 if($obj instanceof employee){//若是员工对象,则显示其工作状态 $obj->working(); }else{//否则显示错误信息 echo "Error: 对象错误!"; } } printworking(new painter());//显示油漆工的工作 printworking(new typist());//显示打字员的工作 printworking(new manager());//显示经理的工作
分析:在上述程序中,先定義一個員工基類,並定義一個員工工作狀態的方法。然後定義將繼承自員工基類別的三個員工類別:油漆工類別、打字員類別和經理類別。然後定義顯示員工工作狀態的方法。並在該方法中建立一個「是一」關係,用於判斷是否為合法的員工。其結果如下所示。
油漆工正在刷漆! 打字员正在打字! 经理正在开会!
從上例可發現,無論增加多少個員工類,只需要實作自員工父類繼承的該員工類別和方法。而無須修改顯示員工工作狀態的方法printworking()。
實作php多態的兩種方法
在PHP5中,變數的型別是不確定的,一個變數可以指向任何型別的數值、字串、物件、資源等。我們無法說PHP5中多態的是變數。
我們只能說在PHP5中,多型應用在方法參數的型別提示位置。
一個類別的任何子類別物件都可以滿足以當前類型作為類型提示的類型要求。
所有實作這個介面的類,都可以滿足以介面類型作為類型提示的方法參數要求。
簡單的說,一個類別擁有其父類別、和已實現介面的身份。
透過實作介面實作多態
<?php interface User{ // User接口 public function getName(); public function setName($_name); } class NormalUser implements User { // 实现接口的类. private $name; public function getName(){ return $this->name; } public function setName($_name){ $this->name = $_name; } } class UserAdmin{ //操作. public static function ChangeUserName(User $_user,$_userName){ $_user->setName($_userName); } } $normalUser = new NormalUser(); UserAdmin::ChangeUserName($normalUser,"Tom");//这里传入的是 NormalUser的实例. echo $normalUser->getName(); ?>
使用介面與組合模擬多重繼承
透過組合模擬多重繼承。
在PHP中不支援多重繼承,如果我們向使用多個類別的方法而實作程式碼重複使用有什麼辦法麼?
那就是组合。在一个类中去将另外一个类设置成属性。
下面的例子,模拟了多重继承。
接口实例
写一个概念性的例子。 我们设计一个在线销售系统,用户部分设计如下: 将用户分为,NormalUser, VipUser, InnerUser 三种。要求根据用户的不同折扣计算用户购买产品的价格。并要求为以后扩展和维护预留空间。
<?php interface User { public function getName(); public function setName($_name); public function getDiscount(); } abstract class AbstractUser implements User { private $name = ""; protected $discount = 0; protected $grade = ""; function construct($_name) { $this->setName($_name); } function getName() { return $this->name; } function setName($_name) { $this->name = $_name; } function getDiscount() { return $this->discount; } function getGrade() { return $this->grade; } } class NormalUser extends AbstractUser { protected $discount = 1.0; protected $grade = "Normal"; } class VipUser extends AbstractUser { protected $discount = 0.8; protected $grade = "VipUser"; } class InnerUser extends AbstractUser { protected $discount = 0.7; protected $grade = "InnerUser"; } interface Product { function getProductName(); function getProductPrice(); } interface Book extends Product { function getAuthor(); } class BookOnline implements Book { private $productName; protected $productPrice; protected $Author; function construct($_bookName) { $this->productName = $_bookName; } function getProductName() { return $this->productName; } function getProductPrice() { $this->productPrice = 100; return $this->productPrice; } public function getAuthor() { $this->Author = "chenfei"; return $this->Author; } } class Productsettle { public static function finalPrice(User $_user, Product $_product, $number) { $price = $_user->getDiscount() * $_product->getProductPrice() * $number; return $price; } } $number = 10; $book = new BookOnline(" 设计模式 "); $user = new NormalUser("tom"); $price = Productsettle::finalPrice($user, $book, $number); $str = "您好,尊敬的" . $user->getName() . "<br />"; $str .= "您的级别是" . $user->getGrade() . "<br />"; $str .= "您的折扣是" . $user->getDiscount() . "<br />"; $str .= "您的价格是" . $price; echo $str; ?>
推荐学习:《PHP视频教程》
以上是PHP中多態性是什麼意思的詳細內容。更多資訊請關注PHP中文網其他相關文章!