首頁 > 後端開發 > php教程 > php物件導向中封裝、繼承、多型三大特徵實例詳解

php物件導向中封裝、繼承、多型三大特徵實例詳解

伊谢尔伦
發布: 2023-03-11 22:08:02
原創
1510 人瀏覽過

PHP物件導向三大特徵學習學習目標:充分理解抽象、封裝、繼承、多型

面象對向的三大特徵:封裝性、繼承性、多態性先簡單理解抽象:
我們在前面定義一個類別的時候,其實就是把一類事物共有的屬性和行為提取出來,形成一個物理模型(模版),這種研究問題的方法稱為抽象
php物件導向中封裝、繼承、多型三大特徵實例詳解
一、封裝性
封裝就是把抽取出來的資料和資料的操作封裝在一起,資料被保護在內部,程式的其他部分只有被授權的操作(方法)才能對資料進行操作。
php提供了三種存取控制修飾符
public 表示全域,本類別內部,類別外部,子類別都可以存取
protected 表示受保護的,只有本類別或子類別可以存取
private 表示私有的,只有本類別內部可以存取
以上三種修飾符既可以修飾方法也可以修飾屬性(變數),方法如果沒有存取修飾符則預設為public,成員屬性必須指定存取修飾符,在PHP4中也有這種寫法var $name,表示公開屬性,不推薦這種寫法
例: 

<?php 
class Person{ 
public $name; 
protected $age; 
private $salary; 
function construct($name,$age,$salary){ 
$this->name=$name; 
$this->age=$age; 
$this->salary=$salary; 
} 
public function showinfo(){ 
//这表示三个修饰符都可以在本类内部使用 
echo $this->name."||".$this->age."||".$this->salary; 
} 
} 
$p1=new Person(&#39;张三&#39;,20,3000); 
//这里属于类外部,那么如果用下面的方法访问age和salary都会报错 
// echo $p1->age; echo$p1->salary; 
?>
登入後複製

那麼現在就想在外部存取protected和private的元素和方法該怎麼辦? 通常做法是透過public函數去存取這些變數格式:

public function setxxxx($val){ 
$this->xxxx=$val; 
} 
public function getxxxx(){ 
return $this->xxxx; 
}
登入後複製

這裡帶set和get只是為了識別方便,並非必要
如:

public function getsalary(){ 
return $this->salary; //扩展:这里可以调用一些方法,如判断用户名等,正确才给访问 
}
登入後複製

在外部就可以透過echo $p1->getsalary();
如果要存取protected和private也可以使用以下方法,但不建議使用,只要了解即可
set() 和get()
set()對protected或private屬性進行賦值操作
set($name,$val);
get()取得protected 或private的值
get($name);
如:

<?php 
class testa{ 
protected $name; 
//使用set()来管理所有属性 
public function set($pro_name,$pro_val){ 
//上面$pro_name和$pro_val可自定义 
//下面$this->pro_name为既定,不可更改 
$this->pro_name=$pro_val; 
} 
//使用get()来获取所有属性值 
public function get($pro_name){ 
if(isset($pro_name)){ 
return $this->pro_name; 
} else { 
return null; 
} 
} 
} 
$n1=new testa(); 
//正常情况,类外部是不能访问protected属性的,但是用了上面的方法就可以对它们进行操作 
$n1->name=&#39;小三&#39;; 
echo $n1->name; 
?>
登入後複製

//以上程式碼看懂就行,不建議使用
二、繼承性
先看一個例子: 

<?php 
class Pupil{ 
public $name; 
protected $age; 
public function getinfo(){ 
echo $this->name.&#39;||&#39;.$this->age; 
} 
public function testing(){ 
echo &#39;this is pupil&#39;; 
} 
} 
class Graduate{ 
public $name; 
protected $age; 
public function getinfo(){ 
echo $this->name.&#39;||&#39;.$this->age; 
} 
public function testing(){ 
echo &#39;this is Graduate&#39;; 
} 
} 
?>
登入後複製

從上面的例子可以看出,當多個類別有很多共同屬性和方法時,程式碼的複用性不高,程式碼冗餘,思考css中的處理方法
解決方法:繼承 

<?php 
class Students{ 
public $name; 
public $age; 
public function construct($name,$age){ 
$this->name=$name; 
$this->age=$age; 
} 
public function showinfo(){ 
echo $this->name.&#39;||&#39;.$this->age; 
} 
} 
class Pupil extends Students{ 
function testing(){ 
echo &#39;Pupil &#39;.$this->name.&#39; is testing&#39;; 
} 
} 
class Graduate extends Students{ 
function testing(){ 
echo &#39;Graduate &#39;.$this->name.&#39; is testing&#39;; 
} 
} 
$stu1=new Pupil(&#39;张三&#39;,20); 
$stu1->showinfo(); 
echo &#39;<br/>&#39;; 
$stu1->testing(); 
?>
登入後複製

從上面可以看出,繼承就是一個子類別(Subclass)透過extends 父類別把父類別(BaseClass)中的public 和protected 的屬性和方法繼續下來,不能繼承private屬性和方法
語法結構:
class 父類別名稱{}
class 子類別名稱extends 父類別名稱{}
細節:
1、一個子類別只能繼承一個父類別(這裡指直接繼承);如果希望繼承多個類別的屬性和方法,可以使用多層繼承
範例: 

<?php 
class A{ 
public $name=&#39;AAA&#39;; 
} 
class B extends A{ 
public $age=30; 
} 
class C extends B{} 
$p=new C(); 
echo $p->name;//这里会输出AAA 
?>
登入後複製

2、在建立某個子類別物件時,預設不會自動呼叫其父類別的建構子
範例:

class A{ 
public function construct(){ 
echo &#39;A&#39;; 
} 
} 
class B extends A{ 
public function construct(){ 
echo &#39;B&#39;; 
} 
} 
$b=new B();//这里会优先输出B中的构造方法,如果B中没有构造方法才会输出A中的
登入後複製

3、在子類別中如果需要存取父類別的方法(建構方法、成員方法方法的修飾符為protected或private) ,那麼可以使用父類別::方法名稱或parent::方法名稱來完成【這裡parent和先前提到的self都均為小寫,大寫報錯】

class A{ 
public function test(){ 
echo &#39;a_test&#39;; 
} 
} 
class B extends A{ 
public function construct(){ 
//两种方法都行 
A::test(); 
parent::test(); 
} 
} 
$b=new B();
登入後複製

5、如果一個子類別(衍生類別)的方法與父類別的方法完全一樣時(public,protected),我們稱為方法覆蓋或方法重寫(override),看下面的多態性
#三、多態性愛
範例: 

<?php 
class Animal{ 
public $name; 
public $price; 
function cry(){ 
echo &#39;i don\&#39;t know&#39;; 
} 
} 
class Dog extends Animal{ 
//覆盖、重写 
function cry(){ 
echo &#39;Wang Wang!&#39;; 
Animal::cry();//这里不会报错,能正确执行父类的cry(); 
} 
} 
$dog1=new Dog(); 
$dog1->cry(); 
?>
登入後複製

小结:
1、当一个父类知道所有的子类都有一个方法,但是父类不能确定该方法如何写,可以让子类去覆盖它的方法,方法覆盖(重写),必须要求子类的方法名和参数个数完全一致
2、如果子类要去调用父类的某个方法(protected/public),可以使用 父类名::方法名 或者 parent::方法名
3、在实现方法重写的时候,访问修饰符可以不一样,但是子类方法的访问权限必须大于等于父类方法的访问权限(即不能缩小父类方法的访问权限)
如 父类public function cry(){} 子类 protected function cry(){} 则会报错
但是子类的访问权限可以放大,如:
父类private function cry(){} 子类 protected function cry(){} 可以正确执行
扩展:
方法重载(overload)
基本概念:函数名相同,但参数的个数或参数的类型不同,达到调用同一个函数,可以区分不同的函数
在PHP5中虽然也支持重载,但是和其它语言还是有很大区别的,php中不能定义多个同名函数
PHP5中提供了强大的“魔术”函数,使用这些魔术函数,我们可以做到函数重载,
这里我们要到到 call,当一个对象调一个方法时,而该方法不存在,则程序会自动调用call
【官方不推荐使用】
PHP中有以下几个魔术常量:LINE FILE DIR FUNCTION CLASS 等
例:

<?php 
class A{ 
function test1($p){ 
echo &#39;test1<br/>&#39;; 
} 
function test2($p){ 
echo &#39;test2<br/>&#39;; 
} 
function call($method,$p){ 
//这里$p为数组,上面两个变量名可自定义 
if($method == &#39;test&#39;){ 
if(count($p)==1){ 
$this->test1($p); 
} else if(count($p)==2){ 
$this->test2($p); 
} 
} 
} 
} 
$a=new A(); 
$a->test(5); 
$a->test(3,5); 
?>
登入後複製


以上是php物件導向中封裝、繼承、多型三大特徵實例詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板