您好,登錄后才能下訂單哦!
<?php
Header("Content-type:text/html;charset=utf-8");
/*********************************
《關(guān)于PHP面向?qū)ο蟮目偨Y(jié)》
**********************************
前言:
1.其實(shí)魔術(shù)方法也是方法是函數(shù),跟前面講的函數(shù)一樣,只不過在類里面有
$this->name這樣的東西,他就是類的成員屬性,他可以在這個(gè)類的任意位置出現(xiàn)。
有可能這個(gè)會擾亂你的思路,你只需分分辨清楚就行了,既然都是
函數(shù)都道理都是一樣的,有的是有計(jì)算功能的,有的有返回值的你用完函數(shù)后打印出來,
或者你不打印,在函數(shù)里面不用return 用輸出都行。
2.$this可以理解為好比是對象的“引用”,我們知道對象訪問他的成員屬性和成員方法時(shí)只能用引用來訪問
$this->name;
$this->say();
3.在類中某個(gè)成員屬性如果在構(gòu)造函數(shù)中不傳入的話,在外部檢測不到這個(gè)成員屬性。
4.$class->nage 這個(gè)東西如果單獨(dú)寫,除了$this,他就是一個(gè)變量,你可以先賦值在輸出試試,
5.魔術(shù)方法是在我們操作對象的時(shí)候自動運(yùn)行,我們不確定他什么時(shí)候運(yùn)行,但是他會自動運(yùn)行。
6.類直接訪問(不用創(chuàng)建對象)方法Person::tell();如果單純的輸入有值,如果里面有$this->什么的,就會報(bào)錯(cuò)了。
一.魔術(shù)方法
__construct()
__destruct()
__set()
__get()
__isset()
__unset()
__call()
__toString()
__autoload()
__sleep()
__wakeup()
__clone()
自動加載類方法
__autoload()
對象串行化方法
serialize()
unserialize()
二.常用的關(guān)鍵字和修飾字
var
public
protected
private
new
extends
final
static
const
instanceof
clone
abstract
interface
implements
三.單例模式
四.關(guān)于多態(tài)性
/
1.構(gòu)造函數(shù)__construct()
構(gòu)造函數(shù)可以接受參數(shù),能夠在創(chuàng)建對象時(shí)賦值給對象屬性
構(gòu)造函數(shù)可以調(diào)用類方法或其他函數(shù)
構(gòu)造函數(shù)可以調(diào)用其他類的構(gòu)造函數(shù)
<?php class Person{ private $name; private $age; private $sex; public function __construct($name,$age,$sex){ $this->name=$name; $this->age=$age; $this->sex=$sex; $this->run($name); } private function run(){ echo $this->name."在跑步"; } public function say(){ echo $this->name."在說話"; } //下面這個(gè)是一個(gè)帶參數(shù) public function say1($name){ echo $name."在說話"; } } $person = new Person("東方不敗",18,'不詳'); $person->say(); $person->say1("nihao"); ?>
調(diào)用父類構(gòu)造函數(shù),調(diào)用其他類的構(gòu)造函數(shù):
public function __constuct(){ parent::__constuct(); classname::__construct(); }
如果想要依次調(diào)用幾個(gè)父類的構(gòu)造函數(shù),可以使用類名直接調(diào)用構(gòu)造函數(shù)
2.析構(gòu)函數(shù)__destuct()
這個(gè)主要是對象在銷毀時(shí)自動調(diào)用的函數(shù),一個(gè)對象在數(shù)去引用時(shí),會自動銷毀。
$a=$b=$c=new Person();
$a = null;
unset($b);
一個(gè)對象三個(gè)引用,失去了兩個(gè)還有一個(gè),程序加載完成后會自動銷毀最后一個(gè)。
3.賦值函數(shù)__set()
__set( $property, $value ) 給一個(gè)未定義的成員屬性賦值時(shí)調(diào)用,(私有成員)
4.取值函數(shù)__get()
__get( $property ) 獲取成員屬性的值(私有成員)
先可以判定下是否有這個(gè)成員
return isset($this->$property) ? $this->$property : null;
class Person{ private $name; private $age; private $sex; public function __construct($name,$age,$sex){ $this->name=$name; $this->age=$age; $this->sex=$sex; $this->run(); } private function run(){ echo $this->name."在跑步".$this->age; } public function say(){ echo $this->name."在說話"; } public function say1($name){ echo $name."在說話"; } public function __set($field,$value){ if($field=="age"){ if($value>200){ // return "非法數(shù)據(jù)"; $value="非法數(shù)據(jù)"; } } $this->$field=$value; } public function __get($field){ return $this->$field; } } $person = new Person("東方不敗",210,'不詳'); $person->say(); // $person->run(); $person->say1("nihao"); echo "<br/>---------------------我是華麗麗的分界線---------------------<br/>"; $person->age=220; echo $person->age;
5.__isset()方法用于檢測私有屬性值是否被設(shè)定。
如果對象里面成員是公有的,可以直接使用 isset() 函數(shù)。如果是私有的成員屬性,
那就需要在類里面加上一個(gè) __isset() 方法,然后再使用isset()函數(shù)如下
public function __isset($property_name)
{
return isset($this->$property_name);
}
這樣當(dāng)在類外部使用 isset() 函數(shù)來測定對象里面的私有成員是否被設(shè)定時(shí),就會自動調(diào)用 __isset() 方法來檢測。
6.__unset()方法用于刪除私有屬性。
同 isset() 函數(shù)一樣,unset() 函數(shù)只能刪除對象的公有成員屬性,當(dāng)要刪除對象內(nèi)部的私有成員屬性時(shí),
需要使用__unset() 方法:
public function __unset($property_name)
{
unset($this->$property_name);
}
7.__call() 方法用于監(jiān)視錯(cuò)誤的方法調(diào)用。
為了避免當(dāng)調(diào)用的方法不存在時(shí)產(chǎn)生錯(cuò)誤,可以使用 __call() 方法來避免。該方法在調(diào)用的方法
不存在時(shí)會自動調(diào)用,程序仍會繼續(xù)執(zhí)行下去。語法:
public function __call($function_name, $arguments)
{
......
}
該方法有兩個(gè)參數(shù),
第一個(gè)參數(shù) $function_name 會自動接收不存在的方法名。
第二個(gè) $args 則以數(shù)組的方式接收不存在的方法的多個(gè)參數(shù)。
8.__toString()方法用來輸出對象的引用
這個(gè)方法也是一樣自動被調(diào)用的,是在 直接輸出對象引用時(shí)自動調(diào)用的, 前面我們講過對象引用是一個(gè)指針,
比如說:“$p=new Person()”中,$p 就是一個(gè)引用,我們不能使用echo 直接輸出$p,這樣會輸出"Catchable fatal
error: Object of class Person could not be converted to string"這樣的錯(cuò)誤,如果你在類里面定義
了"__toString()"方法,在直接輸出對象引用的時(shí)候,就不會產(chǎn)生錯(cuò)誤,而是自動調(diào)用了 "__toString()"方法,
輸出"__toString()"方法中返回的字符,所以"__toString()"方法一定 要有個(gè)返回值(return 語句)。
9.__autoload()方法用于自動加載其他文件中的類。
這個(gè)方法是唯一一個(gè)不在類中寫的方法。
function __autoload($classname){
include_once ucfirst($classname)."Controller.php";
}
10.__sleep()方法是對象在序列化時(shí)執(zhí)行的方法
注意了,對象在序列化后里面保存的只是他的屬性(初始化的時(shí)候賦值了),函數(shù)和方法都是類的,不是對象的。這點(diǎn)要明確
11.__wakeup()方法是對象在反序列化時(shí)執(zhí)行的方法.
在wake.php中
class db { private $host; private $user; private $pwd; private $dbname; private $mysqli; function __construct($host, $user, $pwd, $dbname) { $this->host = $host; $this->user = $user; $this->pwd = $pwd; $this->dbname = $dbname; $this->db(); } function db() { $this->mysqli = new mysqli ( $this->host, $this->user, $this->pwd, $this->dbname ); } function select() { $this->mysqli->query("SET CHARSET GBK"); $sql = "SELECT * FROM ams_archives_rs LIMIT 0,4"; $result = $this->mysqli ->query ( $sql ); $rows = array (); while ( $row = $result->fetch_assoc () ) { $rows [] = $row; } ECHO "<PRE>"; print_r ( $rows ); } function __sleep(){ return array_keys(get_object_vars($this)); } function __wakeup(){ $this->db(); } } session_start(); $chanel = new db("localhost",'root','admin888','ams'); //$chanel->select(); $_SESSION['channel_obj'] = serialize($chanel);
在wakeupa.php中
session_start(); include 'wakeup.php'; $channel_obj=unserialize($_SESSION['channel_obj']); $channel_obj->select(); //如果在59.php中不寫上__wakeup()方法會連接不上 11.__clone()這個(gè)使用關(guān)鍵字clone時(shí)自動運(yùn)行的方法 public function __clone(){ $this->class=2; } $person1=clone $person; echo $person1->class;
二、這幾個(gè)關(guān)鍵字我們挑選幾個(gè)不常用的看看
1.const
他在類的內(nèi)部使用的方法如下
self::常量名大寫;
他在類的外部使用方法
類名::常量名大寫;
2.extends 英文extend的第三人稱單數(shù)是擴(kuò)展繼承的意思
3.final
可以修飾類和方法
修飾類,這個(gè)類不能被繼承
修飾方法,這個(gè)方法不能被重寫
4.static
翻譯中文是靜態(tài)的意思
用來修飾成員屬性和方法
如果用來修飾成員屬性,初始化后的所有對象都是共用這個(gè)成員屬性。
他在類的內(nèi)部使用方法如下
public function getName(){ //return 類名::靜態(tài)變量; //return self::靜態(tài)變量; //return Person::$name; return self::$name; } public function setName($val){ Person::$name=$val; //self::$name=$val; }
$p->setName('東方不敗');
//這里設(shè)置后所有的對象name都是東方不敗了
他在類的外部使用的方法如下
Person::$name;//只能用類名::方法名
如果是用來修飾成員方法,他就不能訪問非靜態(tài)成員,因?yàn)榉庆o態(tài)的成員必須用對象的引用來訪問。
因此,用static修飾的方法里面就一定不使用非靜態(tài)成員
5.instanceof
這個(gè)是用來判斷一個(gè)對象是不是某個(gè)類實(shí)例化出來的
$p=new Person();
echo intval($p instanceof Person);
//還有一個(gè)函數(shù)也可以
echo intval(is_a($p,'Person');//PHP官方不建議使用
還有一個(gè)函數(shù)是用來判斷一個(gè)對象是不是某個(gè)類的子類實(shí)例化出來的(父親級別)
is_subclass_of($p,'Pseson');
6.abstract
中文意思是抽象的意思
這個(gè)關(guān)鍵字既可以修飾類也可以修飾方法
關(guān)于抽象方法:沒有方法體的方法稱作抽象方法,注意在類中聲明抽象方法必須有abstract修飾
function fun();
關(guān)于抽象類:如果一個(gè)類中有abstract修飾的方法那么這個(gè)類就是抽象類
abstract class Person{
abstract function fun();
}
抽象類是為了規(guī)定一些共性的成員,一般是給了N個(gè)抽象類,抽象類自己不
被實(shí)例化,必須由子類繼承過來(所以子類就不能再是抽象類了,而且非抽象方法和成員屬性的訪問
權(quán)限也就必須得protected和public),而且子類必須逐一實(shí)現(xiàn)這N個(gè)抽象方法;而且實(shí)現(xiàn)的方法必須
是public 或者不寫;
7.interface
中文意思為接口
PHP是單繼承,每個(gè)類只能繼承一個(gè)父類
他是一種特殊的類,
接口里面的成員必須全是public權(quán)限,
接口里面的方法全都是抽象方法,并且不能用abstract修飾,
接口里的成員屬性只能是常量(const NAME='hby');
可以寫另外一個(gè)接口來繼承(extends)一個(gè)接口,用來擴(kuò)展里面的方法。
可以寫一個(gè)抽象類來實(shí)現(xiàn)(implements)一個(gè)接口,用來實(shí)現(xiàn)里面的部分方法
可以寫一個(gè)普通類來實(shí)現(xiàn)(implements)一個(gè)接口,用來實(shí)現(xiàn)里面的全部方法
一個(gè)類可以同時(shí)繼承父類還實(shí)現(xiàn)N個(gè)接口.
class 類名 extends 父類名 implements 接口1,接口2,...接口n{
//實(shí)現(xiàn)所有接口中的抽象方法;
}
三、單例模式
網(wǎng)上說的意思?xì)w結(jié)到一點(diǎn)就是:讓一個(gè)類只有一個(gè)實(shí)例.
如何做到呢?
1.前面學(xué)過,每次用 new 類名 的方式,就可以創(chuàng)建一個(gè)對象。我們必須禁止
外部程序用 new 類名的方式來創(chuàng)建多個(gè)實(shí)例。
解決辦法是:我們將構(gòu)造函數(shù)設(shè)置成 private ,讓構(gòu)造函數(shù)只能在內(nèi)部被調(diào)用,
而外部不能調(diào)用。這樣,這個(gè)類就不能被外部用 new 的方式建立多個(gè)實(shí)例了。
class A{
private function __construct(){}
}
$a = new A();
2.我們已經(jīng)禁止外部用new實(shí)例化這個(gè)類,我們改如何讓用戶訪問這個(gè)類呢?前門堵了,
我們需要給用戶留個(gè)后門。
解決辦法是:static 修飾的方法,可以不經(jīng)實(shí)例化一個(gè)類就可以直接訪問這個(gè)方法。
class A{ private function __construct(){} static function getClassA(){ return "這里是后門,可以通過這里進(jìn)入類內(nèi)部.."; } } echo A::getClassA();
3.雖然我們已經(jīng)進(jìn)入類內(nèi)部,但我們要的是這個(gè)類的唯一實(shí)例?先不管別的,
我們先需要一個(gè)實(shí)例。通過這個(gè)static的方法返回這個(gè)實(shí)例,如何做呢?
下面的例子我們確實(shí)返回了A類的實(shí)例,但注意兩次執(zhí)行返回的不是同一個(gè)實(shí)例。
class A{ private function __construct(){} static function getClassA(){ $a = new A(); return $a; } }
// 看到這里確實(shí)返回的是 A 的實(shí)例.但不是同一個(gè)對象.
$a1 = A::getClassA(); $a2 = A::getClassA(); echo "\$a1 的類是 ".get_class($a1)." , \$a2 是 ".get_class($a1); if($a1 === $a2){ echo "<br> \$a1 \$a2 指向同一對象."; }else{ echo "<br> \$a1 \$a2 不是一個(gè)對象."; }
4.我們已經(jīng)通過static方法返回了A的實(shí)例。但還有問題。我們?nèi)绾伪WC我們
多次操作獲得的是同一個(gè)實(shí)例的呢?解決辦法:static的屬性在內(nèi)部也只有一個(gè)。
static 屬性能有效的被靜態(tài)方法調(diào)用。將這個(gè)屬性也設(shè)置成private,以防止外部調(diào)用。
先將這個(gè)屬性設(shè)置成 null。每次返回對象前,先判斷這個(gè)屬性是否為 null 。
如果為 null 就創(chuàng)建這個(gè)類的新實(shí)例,并賦值給這個(gè) static 屬性。如果不為空,
就返回這個(gè)指向?qū)嵗?static 屬性。
class A{ private static $a = null; private function __construct(){} static function getClassA(){ if( null == self::$a){ self::$a = new A(); } return self::$a; } } // 看到這里確實(shí)返回的是 A 的實(shí)例.但不是同一個(gè)對象. $a1 = A::getClassA(); $a2 = A::getClassA(); echo "\$a1 的類是 ".get_class($a1)." , \$a2 是 ".get_class($a1); if($a1 === $a2){ echo "<br> \$a1 \$a2 指向同一對象."; }else{ echo "<br> \$a1 \$a2 不是一個(gè)對象."; }
最終這里無論是多少次都是同一個(gè)對象。
下面給一個(gè)例子
<?php class Database { private $_db; static $_instance; final private function __construct($dbname,$user='root',$password='',$port='3306') { $conStr = "dbname=".$dbname." user=".$user." password=".$password." port=".$port; $this->_db = pg_connect($conStr); } private __clone() {};//不允許被克隆 public static function getInstance($dbname,$user='root',$password='',$port='3306') { if( ! (self::$_instance instanceof self) ) { self::$_instance = new self($dbname,$user='root',$password='',$port='3306'); } return self::$_instance; } public function query($sql) { return pg_query($this->_db, $sql); } } ?>
代碼從這開始
**/
class Person{ const HIGH='170'; private $name; private $age; private $sex; public $class; public function __construct($name,$age,$sex,$class){ $this->name=$name; $this->age=$age; $this->sex=$sex; $this->class=$class; $this->run(); } private function run(){ echo $this->name."在跑步".$this->age; } public function say(){ echo $this->name."在說話"; } public function say1($name){ echo $name."在說話"; } public function __set($field,$value){ if($field=="age"){ if($value>200){ // return "非法數(shù)據(jù)"; $value="非法數(shù)據(jù)"; } } $this->$field=$value; } public function __get($field){ return $this->$field; } public function __isset($property_name){ return isset($this->$property_name); } public function __unset($property_name){ unset($this->$property_name); } public function __call($function_name,$arguments){ echo "您所調(diào)用的方法".$function_name."參數(shù)<br/>"; echo var_dump($arguments)."不存在"; } public function __toString(){ return $this->name."qwertyuiop"; } public function __clone(){ $this->class='2'; } public function tellhigh(){ echo "身高是".self::HIGH; } } $person = new Person("東方不敗",210,'不詳','大學(xué)'); $person->say(); // $person->run(); $person->say1("nihao"); echo "<br/>---------------------我是華麗麗的分界線---------------------<br/>"; $person->age=220; echo $person->age; echo "<br/>---------------------我是華麗麗的分界線---------------------<br/>"; echo isset($person->class) ? "存在":"不存在"; echo "<br/>---------------------我是華麗麗的分界線---------------------<br/>"; unset($person->age); echo isset($person->class) ? "存在":"不存在"; echo isset($person->age) ? "存在":"不存在"; echo "<br/>---------------------我是華麗麗的分界線---------------------<br/>"; $person->age=80; echo isset($person->age) ? "存在":"不存在"; echo "<br/>---------------------我是華麗麗的分界線---------------------<br/>"; $person->drink(123,"we"); echo "<br/>---------------------我是華麗麗的分界線---------------------<br/>"; echo $person;//輸出對象的引用 echo "<br/>---------------------我是華麗麗的分界線---------------------<br/>"; //下面寫一個(gè)自動加載函數(shù) function __autoload($classname){ include_once ucfirst($classname)."Controller.php"; } $mx=new Phone(1999,'4.5英寸','2200mah','魅族MX2','MX2'); $mx->tell(); echo Phone::FUNC; echo "<br/>---------------------我是華麗麗的分界線---------------------<br/>"; $person1=clone $person; echo intval($person1===$person); echo $person1->class; echo "<br/>---------------------我是華麗麗的分界線---------------------<br/>"; $person->tellhigh(); echo "<br/>---------------------我是華麗麗的分界線---------------------<br/>"; echo Person::HIGH; echo "<br/>---------------------我是華麗麗的分界線---------------------<br/>"; abstract class Student{ abstract function say(); abstract function study(); public function tell(){ echo "這是個(gè)抽象類里面的普通方法"; } } class LStudent extends Student{ public function a(){ echo "我是LStudent類中的a方法"; } public function say(){ echo "重寫抽象類中的say方法"; } function study(){ echo "重寫抽象類中的study方法"; } } $LS=new LStudent(); $LS->a(); echo "<br/>---------------------我是華麗麗的分界線---------------------<br/>"; $LS->say(); echo "<br/>---------------------我是華麗麗的分界線---------------------<br/>"; interface PS{ const NAME='串口'; function start(); function work(); } interface PS1 extends PS{ function stop(); } abstract class PS2 implements PS{ function start(){ echo "抽象類實(shí)現(xiàn)部分方法這里是start方法"; } } class PS3 implements PS1{ function start(){ echo "抽象類實(shí)現(xiàn)全部方法這里是start方法"; } function work(){ echo "抽象類實(shí)現(xiàn)全部方法這里是work方法"; } function stop(){ echo "抽象類實(shí)現(xiàn)全部方法這里是stop方法"; } } $ps=new PS3(); $ps->start(); echo "<br/>---------------------我是華麗麗的分界線---------------------<br/>"; echo PS::NAME; ?>
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。