1、了解解構函式的定義
2、了解解構函式的作用
3、了解解構函式的特點
4、掌握物件參照賦值的概念和特點
1、定義:它是一個特殊的函數
public function destruct(){}
2、作用:清理物件,釋放記憶體
3、特點:
1、自動執行,而非手動呼叫
2、類一旦定義了解構函式,程式結束前就會銷毀該類下的所有範例物件
3、在應用程式結束前的最後一刻執行,除非一些特殊情況,比如第4點,或者當物件的生命週期結束以後也會自動執行
4、 一旦我們手動的銷毀一個物件,系統會自動的觸發該物件的解構函式
特別注意一個特殊的情況:就是如果物件還被其他物件參照的情況下,它的解構函式也不會被觸發
5、在物件的生命週期結束前執行
6、應用程式結束前的最後一刻,會銷毀掉還未銷毀的物件,已經銷毀的物件不會再次被銷毀
進一步得出,一個物件的解構函式只能執行1次,不會執行多次
7、在php中如果我們不為類定義個解構函式,那麼php會自動的為類建立一個解構函式,然後在
程式結束前呼叫預設的解構函式,但是一旦定義了解構函式,就會執行我們寫的解構函式
進一步我們就可以在自己的解構函式裡寫自己的業務程式碼
比如如果程式使用了印表機資源,我們可以銷毀物件前釋放印表機資源
相關的程式碼如下:
<?php class NbaPlayer{ public $name = "";//姓名 public $height = "";//身高 public $weight = "";//體重 public $team = "";//團隊 public $playerName = "";//球員號碼 public function __construct( $name,$height,$weight,$team,$playerName ){ $this->name = $name; $this->height=$height; $this->weight = $weight; $this->team = $team; $this->playName = $playerName; echo "建構函式執行了,當前物件是{$this->name}<br/>"; } //解構函式 public function __destruct(){ echo "銷毀物件".$this->name."<br/>"; } //跑步 public function run(){ echo "跑步中<br/>"; } //跳躍 public function jump(){ echo "跳躍<br/>"; } //運球 public function dribble(){ echo "運球<br/>"; } //傳球 public function pass(){ echo "傳球<br/>"; } //投籃 public function shoot(){ echo "投籃<br/>"; } //扣籃 public function dunk(){ echo "扣籃<br/>"; } } //建立喬丹物件 $jordon = new NbaPlayer("喬丹","1.98米","98公斤","公牛","23"); //輸出喬丹物件 echo "名稱= ".$jordon->name."<br/>"; //讓喬丹跑步 $jordon->run(); //建立科比物件 $kobe = new NbaPlayer("科比","2米","93公斤","湖人","24"); //建立詹姆斯物件 $james = new NbaPlayer("詹姆斯","2.03米","120公斤","熱火","6"); $james1 = new NbaPlayer("詹姆斯1","2.03米","120公斤","熱火","6"); $james2 = new NbaPlayer("詹姆斯2","2.03米","120公斤","熱火","6"); $jordon = null;//手動的銷毀了物件 ,此時喬丹物件的解構函式將會被觸發 $kobe = null;//手動的銷毀了物件 ,此時科比物件的解構函式將會被觸發 echo "<b>程式結束完畢</b><br/>"; ?>
接下來,我程式碼修改如下,新增一個Mysql資料庫連線類,然後在NbaPlayer建構函式裡面呼叫它
這是Mysql.class.php,裡面定義了一個解構函式
<?php //資料庫類 class Mysql{ //定義屬性 public $conn = ""; //建構函式 public function __construct( ){ //初始化行為 初始化方法 $this->initConn(); } //解構函式 銷毀資料庫連線 public function __destruct(){ //銷毀連線 if( $this->conn ){ mysqli_close( $this->conn ); echo "銷毀了連線<br/>"; } } //定義方法 //建立公共的方法 獲取資料庫連線 public function initConn(){ $config = Array( "hostname"=>"127.0.0.1", "database"=>"Nbaplayer", "username"=>"root", "password"=>"root" ); $this->conn = mysqli_connect( $config['hostname'],$config['username'] ,$config['password'], $config['database']); } } ?>
接下來還是定義個NbaPlayer類,但是為了突出重點,所以NbaPlayer類我會簡寫如下:
<?php require_once "Mysql.class.php"; class NbaPlayer{ public $name = "";//姓名 public $height = "";//身高 public $weight = "";//體重 public $team = "";//團隊 public $playerName = "";//球員號碼 public $conn = "";//新增一個資料庫連線屬性 public function __construct( $name,$height,$weight,$team,$playerName ){ $this->name = $name; $this->height=$height; $this->weight = $weight; $this->team = $team; $this->playName = $playerName; //初始化資料庫連線屬性 $mysql = new Mysql(); $this->conn = $mysql->conn; } //新增獲取所有Nba球員的方法 public function getAll(){ //建立資料庫連線 $conn = $this->conn; //寫sql $sql = " select * from ".$this->tableName; //執行sql $result = mysqli_query( $conn,$sql ); //獲取資料 // mysqli_fetch_all($result)//特點:不會包含欄位名 $list = Array(); while( $row = mysqli_fetch_assoc( $result ) ){ $list[] = $row; } //返回資料 return $list; } } //建立喬丹物件 $jordon = new NbaPlayer("喬丹","1.98米","98公斤","公牛","23"); $list = $jordon->getAll(); echo "<b>程式結束完畢</b><br/>"; ?>
當你執行,你會發現錯誤,會發現連線已經被銷毀,在getAll函數呼叫之前,也就是說,一旦 範例化了 $jordon = new NbaPlayer("喬丹","1.98米","98公斤","公牛","23");
資料庫連線物件就銷毀了,其實如果你去偵錯,你會發現,建構函式裡的mysql物件其實是在NbaPlayer類別建構函式的最後一個}執行完成後,它就會被銷毀,為什麼呢
這其實就涉及到變數作用域的問題,因為mysql物件是在建構函式裡定義的,所以外面是無法存取到它的,所以一旦建構函式執行完成後,系統會認為它將不再有用,所以就會
把它清理掉,從而執行它的解構函式,所以最終你去呼叫getAll方法的時候,資料庫連線都早已斷開,自然無法再去執行sql,
其實想要解決掉這個問題,那麼就需要了解物件參照,我們可以結合物件參照來解決這個問題,接下來先來了解物件參照
總結:
1、變數1=變數2=物件 會建立物件的2個獨立參照,但是他們指向的還是同一個物件,所以還是會互相影響
2、變數1=&變數2 只會建立物件的一個參照,因為它們使用同一個物件參照
3、一個物件有沒有用,就要看它是否完全沒有被參照了,如果沒有任何變數參照它,它就真的沒用了,
才會被銷毀,進而它的解構函式才會得以執行
4、變數1=clone 變數2=物件,不會建立物件的新參照,而是仿造了一個新的該物件,具有該物件通用的屬性和方法
相關程式碼如下:
<?php class NbaPlayer{ public $name = "";//姓名 public $height = "";//身高 public $weight = "";//體重 public $team = "";//團隊 public $playerName = "";//球員號碼 public function __construct( $name,$height,$weight,$team,$playerName ){ $this->name = $name; $this->height=$height; $this->weight = $weight; $this->team = $team; $this->playName = $playerName; echo "建構函式執行了,當前物件是{$this->name}<br/>"; } public function __destruct(){ echo "銷毀物件".$this->name."<br/>"; } //跑步 public function run(){ echo "跑步中<br/>"; } //跳躍 public function jump(){ echo "跳躍<br/>"; } //運球 public function dribble(){ echo "運球<br/>"; } //傳球 public function pass(){ echo "傳球<br/>"; } //投籃 public function shoot(){ echo "投籃<br/>"; } //扣籃 public function dunk(){ echo "扣籃<br/>"; } } //建立喬丹物件 $jordon = new NbaPlayer("喬丹","1.98米","98公斤","公牛","23"); //輸出喬丹物件 echo "名稱= ".$jordon->name."<br/>"; //讓喬丹跑步 $jordon->run(); //建立科比物件 $kobe = new NbaPlayer("科比","2米","93公斤","湖人","24"); //建立詹姆斯物件 $james = new NbaPlayer("詹姆斯","2.03米","120公斤","熱火","6"); $james1 = new NbaPlayer("詹姆斯1","2.03米","120公斤","熱火","6"); $james2 = new NbaPlayer("詹姆斯2","2.03米","120公斤","熱火","6"); $jordon1 = $jordon;//&符號表示左邊物件和右邊物件其實就是一個物件 $jordon = null;//手動的銷毀了物件 echo "<b>程式結束完畢</b><br/>"; ?>
重點解析:本來不加$jordon1 = $jordon;當程式執行到$jordon=null,喬丹物件的解構函式將會被執行,也就是說 「銷毀物件喬丹」在「程式結束完畢」 前顯示
但是加了這句以後,你會發現執行到$jordon=null的時候,喬丹物件的解構函式並沒有馬上執行,而是到應用程式結束後才被系統自動執行 ,也就是說
「銷毀物件喬丹」在「程式結束完畢」 後顯示
為什麼會這樣:
接下來就來具體分析$jordon1 = $jordon 這行程式碼到底讓系統做了什麼事情
結合上面的程式碼,其實我們寫的程式碼順序是
$jordon = new NbaPlayer("喬丹","1.98米","98公斤","公牛","23");
$jordon1 = $jordon;
那麼$jordon = new NbaPlayer("喬丹","1.98米","98公斤","公牛","23");
說明就是
1、建立了喬丹物件
2、建立了一個變數,變數名叫jordon
3、創了一個喬丹物件的獨立參照,就是上圖的箭頭
然後$jordon1 = $jordon;
說明就是
1、建立了一個新的變數,名叫jordon1
2、又建立了一個喬丹物件的獨立參照,就是上圖的第二個箭頭
那麼說明 喬丹物件此時被兩個變數參照,當我們$jordon=null 的時候,喬丹物件還被jordon1變數參照,所以此時喬丹物件還有用,還有用就不能當做垃圾清理掉,
所以這就可以解釋上面的問題,喬丹物件 在最後 才會被系統銷毀,所以要看一個物件是否有用,要看它到底還存不存在變數參照,如果完全不存在變數參照了,那麼這個
物件才可以被視作完全無用,它的解構函式才會被執行
好這是物件參照賦值的一種形式,還有另外一種 就是 =&
程式碼如下:
<?php class NbaPlayer{ public $name = "";//姓名 public $height = "";//身高 public $weight = "";//體重 public $team = "";//團隊 public $playerName = "";//球員號碼 public function __construct( $name,$height,$weight,$team,$playerName ){ $this->name = $name; $this->height=$height; $this->weight = $weight; $this->team = $team; $this->playName = $playerName; echo "建構函式執行了,當前物件是{$this->name}<br/>"; } public function __destruct(){ echo "銷毀物件".$this->name."<br/>"; } //跑步 public function run(){ echo "跑步中<br/>"; } //跳躍 public function jump(){ echo "跳躍<br/>"; } //運球 public function dribble(){ echo "運球<br/>"; } //傳球 public function pass(){ echo "傳球<br/>"; } //投籃 public function shoot(){ echo "投籃<br/>"; } //扣籃 public function dunk(){ echo "扣籃<br/>"; } } //建立喬丹物件 $jordon = new NbaPlayer("喬丹","1.98米","98公斤","公牛","23"); //輸出喬丹物件 echo "名稱= ".$jordon->name."<br/>"; //讓喬丹跑步 $jordon->run(); //建立科比物件 $kobe = new NbaPlayer("科比","2米","93公斤","湖人","24"); //建立詹姆斯物件 $james = new NbaPlayer("詹姆斯","2.03米","120公斤","熱火","6"); $james1 = new NbaPlayer("詹姆斯1","2.03米","120公斤","熱火","6"); $james2 = new NbaPlayer("詹姆斯2","2.03米","120公斤","熱火","6"); $jordon1 = &$jordon;//&符號表示左邊物件和右邊物件其實就是一個物件 $jordon = null;//手動的銷毀了物件 echo "<b>程式結束完畢</b><br/>"; ?>
當我們把上面的程式碼僅僅加上一個 &,也就是把$jordon1 = $jordon 改成 $jordon1 =& $jordon,你會發現結果又變了
變成什麼呢,就是當執行$jordon=null的時候,喬丹物件的解構函式還是被執行了,為什麼呢
我們再來看下 $jordon1 = & $jordon 做了什麼事情
系統所做事情如下:
1、建立變數,jordon1
2、然後不會再次建立喬丹物件參照,$jordon1通過$jordon變數來使用同一個物件參照來存取喬丹物件
所以此時喬丹物件,只有一個物件參照,不是2個,所以當我們$jordon=null的時候,其實就是銷毀了那唯一的物件參照,進而導致喬丹物件完全沒有了物件參照,所以他的解構函式此時會被觸發執行
不管是$jordon1=$jordon 還是 $jordon1=&jordon ,修改任意變數裡面的名稱,都會導致另外變數的名稱被修改掉,因為他們都是參照的同一個喬丹物件
其實物件賦值,除了上面2種方式外,還有第三種,就是 clone(淺複製) ,也就是比如$jordon1 = clone $jordon;
那這樣的賦值方式它究竟又是什麼意思呢,其實相當於 仿造了 一個喬丹物件
接下來我們通過程式碼演示
<?php class NbaPlayer{ public $name = "";//姓名 public $height = "";//身高 public $weight = "";//體重 public $team = "";//團隊 public $playerName = "";//球員號碼 public function __construct( $name,$height,$weight,$team,$playerName ){ $this->name = $name; $this->height=$height; $this->weight = $weight; $this->team = $team; $this->playName = $playerName; // echo "建構函式執行了,當前物件是{$this->name}<br/>"; } public function __destruct(){ echo "銷毀了物件".$this->name."<br/>"; } //跑步 public function run(){ echo "跑步中<br/>"; } //跳躍 public function jump(){ echo "跳躍<br/>"; } //運球 public function dribble(){ echo "運球<br/>"; } //傳球 public function pass(){ echo "傳球<br/>"; } //投籃 public function shoot(){ echo "投籃<br/>"; } //扣籃 public function dunk(){ echo "扣籃<br/>"; } } //建立喬丹物件 $jordon = new NbaPlayer("喬丹","1.98米","98公斤","公牛","23"); $jordon1 = clone $jordon; $jordon1 = null; $jordon = null; echo "應用程式結束<br/>"; ?>
執行結果如下:
所以$jordon1=clone $jordon;其實就是 仿造了一個喬丹物件,擁有和喬丹物件一樣的屬性和方法
到目前為止,我們了解了物件參照,那麼結合物件參照,我們如何解決最開始的那個問題呢?
大家思考一下再看下面的解決方案
....................................
好,接下來我們來看上面我們遇到的問題
問題是:mysql物件在建構函式執行完畢後,就被銷毀了,導致後面getAll函數裡的資料庫連線無法使用
解決思路:
1.mysql物件在建構函式執行完成後,就被銷毀了,說明mysql物件此時沒有了物件參照
2.那我們就要讓他在建構函式執行完成後,依然存在物件參照,那麼mysql物件就還有用,還有用就不會被銷毀
3.在建構函式裡,建立mysql物件的參照,讓它在建構函式執行完成後,這個參照依然存在
4.我們可以定義個類的新屬性比如$mysql,然後讓$this->mysql = $mysql;這樣就建立了一個mysql物件的獨立參照,而且當建構函式執行完成後
類的mysql屬性還有用,所以這個物件參照還有用,進而mysql物件還有用,就不會被銷毀
具體程式碼如下:
<?php require_once "Mysql.class.php"; class NbaPlayer{ public $name = "";//姓名 public $height = "";//身高 public $weight = "";//體重 public $team = "";//團隊 public $playerName = "";//球員號碼 public $conn = "";//新增一個資料庫連線屬性 public $mysql = "";//新增一個mysql屬性 public function __construct( $name,$height,$weight,$team,$playerName ){ $this->name = $name; $this->height=$height; $this->weight = $weight; $this->team = $team; $this->playName = $playerName; //初始化資料庫連線屬性 $mysql = new Mysql(); $this->conn = $mysql->conn; //解決問題的重點程式碼 $this->mysql = $mysql;//加了這行程式碼,getAll中的conn 資料庫連線就不會銷毀 } //新增獲取所有Nba球員的方法 public function getAll(){ //建立資料庫連線 $conn = $this->conn; //寫sql $sql = " select * from ".$this->tableName; //執行sql $result = mysqli_query( $conn,$sql ); //獲取資料 // mysqli_fetch_all($result)//特點:不會包含欄位名 $list = Array(); while( $row = mysqli_fetch_assoc( $result ) ){ $list[] = $row; } //返回資料 return $list; } } //建立喬丹物件 $jordon = new NbaPlayer("喬丹","1.98米","98公斤","公牛","23"); $list = $jordon->getAll(); echo "<b>程式結束完畢</b><br/>"; ?>
好了,最後我們再稍微做下總結:
1、了解了解構函式的定義,它其實就是一個特殊函數
2、了解了解構函式的作用,就是8個字,清理物件,釋放記憶體
3、了解了解構函式的特點,特點有點多,主要7點
4、知道了物件參照的3種賦值方式,一個是=一個是=&,還有一個是clone
以上就是php物件導向之解構函式和物件參照的詳細內容,更多請關注TW511.COM其它相關文章!