PHP面向物件 基礎語法 構造方法 析構方法 繼承 多型
阿新 • • 發佈:2020-12-08
面向物件介紹
-
概述
- 面向物件是一個程式設計思想。程式設計思想有面向過程和麵向物件
- 面向過程:程式設計思路集中的是過程上
- 面向物件:程式設計思路集中在參與的物件
- 面向物件是一個程式設計思想。程式設計思想有面向過程和麵向物件
-
好處
- 多人合作方便
- 減少程式碼冗餘,靈活性高
- 程式碼的可重用性發揮到極致
- 可擴充套件性強
-
名詞
- OOP:面向物件程式設計(Object Oriented Programming,面向物件程式設計)
- OOA: 面向物件分析(Object-Oriented Analysis,OOA)
- OOD: 面向物件設計(Object-Oriented Design,OOD)
類和物件
-
概念
- 物件是具體存在的事物,物件是由屬性(變數)和方法(函式)組成的
- 類是具有相同屬性和行為的一組物件的集合
- 一個類可以建立多個物件
-
理解
- 物件是由屬性和方法組成的
- 類是所有物件的相同屬性和方法的集合
- 在開發的時候先寫類,通過類建立物件,通過物件呼叫方法和屬性
- 一個類可以建立多個物件
在PHP中實現類和物件
建立類
- 語法
class 類名{
//屬性
//方法
//常量
}
- 概念
- 類是由屬性、方法、常量組成的
- 也可以說類成員有:屬性、方法、常量
類名的命名規則
- 規則
- 以字母、下劃線開頭,後面跟的是字母、數字、下劃線
- 不能用PHP關鍵字做類名
- 類名不區分大小寫(變數名區分,關鍵字、類名不區分大小寫)
- 類名用帕斯卡命名法(大駝峰 單詞的首字母大寫)
<?php
class Student {
//屬性
//方法
//常量
}
?>
物件例項化
- 通過new關鍵字來例項化物件。
- 小括號可以省略
<?php
//定義類
class Student {
//屬性
//方法
//常量
}
//例項化物件
$stu1=new Student();
$stu2=new Student;
var_dump($stu1,$stu2);
?>
物件的比較
- 概述
- 相等:結構和儲存的值一樣就相等
- 全等:指向同一個物件才是全等
- 物件的傳遞是地址傳遞
<?php //定義類 class Student { } //例項化物件 $stu1=new Student(); $stu2=new Student; $stu3=$stu2; //物件傳遞的是地址 var_dump($stu1==$stu2); //bool(true) ,比較物件的結構 echo '<br>'; var_dump($stu1===$stu2); //bool(false) $stu1和$stu2是否是同一個物件 echo '<br>'; var_dump($stu2===$stu3); //bool(true) $stu2和$stu3是同一個物件 ?>
PHP面向物件語法結構
屬性
- 屬性
- 屬性本質就是變數
- 屬性前面的
public
不能省略 - 通過 -> 呼叫物件的成員
- 物件名 -> 屬性名
- 物件名 -> 方法名()
<?php
//定義類
class Student {
public $name; //屬性
public $add='地址不詳'; //屬性
}
//例項化物件
$stu=new Student();
//print_r($stu); //Student Object ( [name] => [add] => 地址不詳 )
//操作屬性
//1、給屬性賦值
$stu->name='tom';
$stu->add='北京';
//2、獲取屬性的值
echo '姓名:'.$stu->name,'<br>'; //姓名:tom
echo '地址:'.$stu->add,'<br>'; //地址:北京
//3、新增屬性
$stu->age=20;
print_r($stu); //Student Object ( [name] => tom [add] => 北京 [age] => 20 )
echo '<br>';
//4、刪除屬性
unset($stu->add);
print_r($stu); //Student Object ( [name] => tom [age] => 20 )
?>
方法
- 方法
- 方法的本質就是函式
- 方法前面public是可以省略的,如果省略,預設就是public的
<?php
class Student {
//定義方法
public function show() {
echo '這是show方法<br>';
}
//public可以省略,如果省略,預設就是public
function test() {
echo '這是test方法<br>';
}
}
$stu=new Student;
$stu->show(); //呼叫方法
$stu->test();
?>
訪問修飾符
-
用來控制成員的訪問許可權
public(公有的)
在類的內部和外部都能訪問private(私有的)
只能在類的內部訪問protected(受保護的)
在整個繼承鏈上訪問
-
作用
- 保證資料的合法性
- 一般來說,屬性都用私有的,通過公有的方法對私有的屬性進行賦值和取值
this
表示呼叫當前方法的物件
<?php
class Student {
private $name; //私有屬性
private $sex; //私有屬性
//通過公有的方法對私有的屬性進行賦值
public function setInfo($name,$sex) {
if($sex!='男' && $sex!='女'){
echo '性別必須是男或女';
exit;
}
$this->name= $name;
$this->sex= $sex;
}
//顯示資訊
public function getInfo() {
echo '姓名:'.$this->name,'<br>';
echo '性別:'.$this->sex,'<br>';
}
}
//例項化
$stu= new Student;
$stu->setInfo('tom','男');
$stu->getInfo();
echo '<hr>';
$stu2= new Student;
$stu2->setInfo('berry','女');
$stu2->getInfo();
?>
類和物件在記憶體中的分佈
- 說明
- 物件的本質是一個複雜的變數
- 類的本質是一個自定義的複雜資料型別
- 棧區:執行速度快,體積小,儲存基本型別
- 堆區:執行速度稍慢,體積大,儲存複雜型別
- 例項化的過程就是分配記憶體空間的過程
- 物件儲存在堆區,將堆區的地址儲存到棧區
封裝
- 說明
- 封裝就是有選擇性的提供資料
- 通過訪問修飾符來實現封裝
構造方法
- 語法
- 構造方法也叫建構函式,當例項化物件的時候自動執行
- 建構函式可以帶引數,但不能有return
function __construct(){
}
# 注意:前面是兩個下劃線
- 例題
- 在其他語言裡,與類名同名的函式是建構函式,在PHP中不允許這種寫法
<?php
class Student {
public function __construct() {
echo '這是構造方法<br>';
}
}
new Student(); //這是構造方法
new Student(); //這是構造方法
?>
<?php
class Student {
//和類名同名的方法是構造方法,PHP中不建議使用
public function Student() {
echo '這是構造方法<br>';
}
}
new Student(); //這是構造方法
new Student(); //這是構造方法
?>
- 建構函式作用:初始化成員變數
<?php
class Student {
private $name;
private $sex;
//建構函式初始化成員變數
public function __construct($name,$sex) {
$this->name=$name;
$this->sex=$sex;
}
//顯示資訊
public function show() {
echo "姓名:{$this->name}<br>";
echo "性別:{$this->sex}<br>";
}
}
//例項化
$stu= new Student('tom','男');
$stu->show();
?>
析構方法
- 語法
- 當物件銷燬的時候自動呼叫
- 解構函式不可以帶引數
function __destruct(){
}
<?php
class Student {
private $name;
//構造方法
public function __construct($name) {
$this->name= $name;
echo "{$name}出生了<br>";
}
//析構方法
public function __destruct() {
echo "{$this->name}銷燬了<br>";
}
}
//測試
$stu1=new Student('tom');
$stu2=new Student('berry');
$stu3=new Student('ketty');
echo '<hr>';
?>
計算機記憶體管理
-
計算機記憶體管理方式
- 先進先出,先進後出
- 先進先出的記憶體管理方式一般用在業務邏輯中,比如秒殺、購票等等
- 先進後出是計算機的預設記憶體管理方式
-
思考題:先進後出(堆疊)
<?php
class Student {
private $name;
//構造方法
public function __construct($name) {
$this->name= $name;
echo "{$name}出生了<br>";
}
//析構方法
public function __destruct() {
echo "{$this->name}銷燬了<br>";
}
}
//測試
$stu1= new Student('tom');
$stu2= new Student('berry');
$stu3= new Student('ketty');
echo '<hr>';
?>
- 思考題:先進先出(佇列)
<?php
class Student {
private $name;
//構造方法
public function __construct($name) {
$this->name= $name;
echo "{$name}出生了<br>";
}
//析構方法
public function __destruct() {
echo "{$this->name}銷燬了<br>";
}
}
//測試
new Student('tom');
new Student('berry');
new Student('ketty');
echo '<hr>';
?>
- 思考題:???
<?php
class Student {
private $name;
//構造方法
public function __construct($name) {
$this->name= $name;
echo "{$name}出生了<br>";
}
//析構方法
public function __destruct() {
echo "{$this->name}銷燬了<br>";
}
}
//測試
$stu= new Student('tom');
$stu= new Student('berry');
$stu= new Student('ketty');
echo '<hr>';
?>
繼承
-
介紹
- 繼承使得程式碼具有層次結構
- 子類繼承了父類的屬性和方法,實現了程式碼的可重用性
- 使用extends關鍵字實現繼承
- 父類和子類是相對的
-
語法
class 子類 extends 父類 {
}
- 執行過程
- 第一步:在Student類中查詢show(),如果找到就呼叫,找不到就到父類中查詢
- 第二步:在Person類中查詢show()
<?php
class Person {
public function show() {
echo "嘿,人類!<br>";
}
}
class Student extends Person{
}
$stu= new Student();
$stu->show();
?>
子類中呼叫父類成員
- 方法
- 通過例項化父類呼叫父類的成員
- 通過$this關鍵字呼叫父類的成員
<?php
class Person {
public function show() {
echo "嘿,人類!<br>";
}
}
class Student extends Person{
public function test1(){
$person= new Person();
$person->show();
}
public function test2(){
$this->show();
}
}
$stu1= new Student();
$stu1->test1();
echo '<br>';
$stu2= new Student();
$stu2->test2();
?>
protected
- protected
- 受保護的,在整個繼承鏈上使用
<?php
class A {
//在整個繼承鏈上訪問
protected $num= 10;
}
class B extends A {
public function getNum() {
echo $this->num;
}
}
//整個繼承鏈上有A和B
$obj= new B();
$obj->getNum();
?>
<?php
class A {
public function getNum() {
echo $this->num;
}
}
class B extends A {
//在整個繼承鏈上訪問
protected $num= 10;
}
//整個繼承鏈上有A和B
$obj= new B();
$obj->getNum();
?>
<?php
class A {
public function getNum() {
echo $this->num;
}
}
class B extends A {
//在整個繼承鏈上訪問
protected $num= 10;
}
//整個繼承鏈上只有A
$obj= new A();
$obj->getNum();
?>
繼承中的建構函式
-
規則
- 如果子類有建構函式就呼叫子類的,如果子類沒有就呼叫父類的建構函式
- 子類的建構函式呼叫後,預設不再呼叫父類的建構函式
-
語法
- 通過類名呼叫父類的建構函式
- parent關鍵字表示父類的名字,可以降低程式的耦合性
# 通過類名呼叫父類的建構函式
父類類名::__construct();
# 通過parent關鍵字呼叫父類的建構函式
parent::__construct();
<?php
class Person {
//父類的建構函式
public function __construct() {
echo '這是父類<br>';
}
}
class Student extends Person {
//子類的建構函式
public function __construct() {
//通過父類的名字呼叫父類的建構函式
Person::__construct();
//parent表示父類的名字
parent::__construct();
echo '這是子類<br>';
}
}
new Student();
?>
- 案例
<?php
class Person {
protected $name;
protected $sex;
//父類的建構函式
public function __construct($name, $sex) {
$this->name= $name;
$this->sex= $sex;
}
}
class Student extends Person {
private $score;
//子類的建構函式
public function __construct($name, $sex, $score) {
parent::__construct($name, $sex); //呼叫父類建構函式並傳遞引數
$this->score= $score;
}
//顯示資訊
public function getInfo() {
echo "姓名:{$this->name}<br>";
echo "性別:{$this->sex}<br>";
echo "成績:{$this->score}";
}
}
//測試
$stu=new Student('sunny','男',28);
$stu->getInfo();
?>
$this詳解
- 概念
$this
表示當前物件的引用,也就是$this
儲存的當前物件的地址
<?php
class A {
public function __construct(){
var_dump($this);
}
}
class B extends A {
}
new A();
echo '<br>';
new B();
?>
多重繼承
- 概念
- PHP不允許多重繼承,因為多重繼承容易產生二義性
- 如何實現C繼承A和B,使用繼承鏈
多型
- 多型分為兩種:方法重寫和方法過載
方法重寫
- 子類重寫了父類的同名的方法
- 子類的方法必須和父類的方法同名
- 引數個數要一致
- 子類修飾的不能比父類更加嚴格
<?php
class A{
protected function say($name){
echo $name,',狗!<br/>';
}
protected function says($name){
echo $name,',狗!<br/>';
}
}
class B extends A{
public function say($name){
echo $name,',貓!<br/>';
}
}
$per= new B();
$per->say('Sunny');
$per->says('Sunny');
?>
方法過載
- 方法過載
- 在同一個類中,有多個同名的函式,通過引數的不同來區分不同的方法
- PHP不支援方法過載,但是PHP可以通過其他方法來模擬方法過載
<?php
class Overloader {
private $properties= array();
function __get($property_name){
if(isset($this->properties[$property_name])){
return($this->properties[$property_name]);
}else{
return(NULL);
}
}
function __set($property_name, $value){
$this->properties[$property_name]= $value;
}
public function __call($method, $p){
print("Invoking $method()<br>\n");
//print("Arguments: ");
//print_r($args);
if($method == 'display'){
if(is_object($p[0]))
$this->displayObject($p[0]);
else if(is_array($p[0]))
$this->displayArray($p[0]);
else $this->displayScalar($p[0]);
}
}
public function displayObject($p){
echo ("你傳入的是個物件,內容如下:<br>");
print_r($p);
echo "<hr>";
}
public function displayArray($p){
echo ("你傳入的是個陣列,內容如下:<br>");
print_r($p);
echo "<hr>";
}
public function displayScalar($p){
echo ("你傳入的是個單獨變數,內容如下:<br>" . $p);
echo "<hr>";
}
}
$obj= new Overloader();
//呼叫 __set() 給一個不存在的屬性變數賦值
$obj->dynaProp = "Dynamic Content";
//呼叫 __get()
print($obj->dynaProp."<br>\n");
//呼叫 __call()
$obj->dynaMethod("Leon", "Zeev");
// $obj->display(array(1,2,3));
// $obj->display('Cat');
?>
面向物件三大特性
- 特性
- 封裝
- 繼承
- 多型