1.final類和final
final 類不能被繼承彤守,final方法可以被繼承孵坚,但是不能被子類重寫
2. 三種權(quán)限講解
場(chǎng)景 | public | protected | private |
---|---|---|---|
外部訪問 | Y | N | N |
本類中調(diào)用 | Y | Y | Y |
子類中調(diào)用 | Y | Y | N |
3. 靜態(tài)屬性和方法(static)
屬性和方法前面加static就可以不用實(shí)例化可以直接訪問养交,訪問方式:
類名::屬性名/方法名()
4. 類常量(const)
使用const定義類中常量
類中調(diào)用自己的常量用類名::常量名
類中調(diào)用全局常量直接使用常量名
define('PI',3.1415926);
class Math{
const PI = 3.14;
public function test(){
echo Math::PI.'<br>';
}
public function test1(){
echo PI;
}
}
$math=new Math();
$math->test();
$math->test1();
//輸出結(jié)果
3.14
3.1415926
5. 單例模式
思路:
- 當(dāng)實(shí)例化一個(gè)類時(shí),就會(huì)自動(dòng)訪問construct方法,需要阻止外部直接實(shí)例化骗污,給construct加protected權(quán)限
- 開放一個(gè)接口用來實(shí)例化本類着撩,然后讓外部訪問這個(gè)類诅福,但是不實(shí)例化的話訪問不了內(nèi)部方法,所以就需要給接口的方法設(shè)置為靜態(tài)的拖叙,通過類名直接訪問
- 在接口方法中進(jìn)行判斷氓润,此類是否被實(shí)例化,有的話直接返回薯鳍,沒有實(shí)例化之后返回
class Single {
static protected $_ins;
protected function __construct() {
$this->rand = mt_rand(10000,99999);
}
static public function getIns() {
if(Single::$_ins === null) {
Single::$_ins = new Single();
}
return Single::$_ins;
}
}
$a = Single::getIns();
$b = Single::getIns();
print_r($a);
print_r($b);
exit;
//訪問的兩次結(jié)果一樣
但是目前還是有缺陷咖气,當(dāng)用一個(gè)類繼承時(shí),重寫一個(gè)構(gòu)造方法挖滤,此類就可以隨便繼承了崩溪,如下:
class Single {
static protected $_ins;
protected function __construct() {
$this->rand = mt_rand(10000,99999);
}
static public function getIns() {
if(Single::$_ins === null) {
Single::$_ins = new Single();
}
return Single::$_ins;
}
}
class Fs extends Single{
public function __construct(){
}
}
$c = new Fs();
$d = new Fs();
print_r($c);
print_r($d);
//兩次結(jié)果不一樣
所以需要對(duì)上述類進(jìn)行修改,防止構(gòu)造方法被重寫斩松,加上final進(jìn)行限制
class Single {
static protected $_ins;
//final方法被繼承后不能被修改
final protected function __construct() {
$this->rand = mt_rand(10000,99999);
}
static public function getIns() {
if(Single::$_ins === null) {
Single::$_ins = new Single();
}
return Single::$_ins;
}
}
6. self與parent
$this 代表本對(duì)象
self 代表本類 (主要用于單例時(shí)不實(shí)例化而是用類訪問用)
parent 代表 父類(用于繼承的時(shí)候伶唯,想要重寫父類,但是還想要保留父類的方法)
class Single {
protected $ins = null;
protected function __construct() {
$this->rand = mt_rand(10000,99999);
}
public static function getIns() {
if(self::$_ins === null) {
self::$_ins = new self();
}
return self::$_ins;
}
}
class Par {
public function __construct() {
echo mt_rand(10000,99999).'<br />';
}
}
class Son extends Par {
public function __construct() {
//ThinkPHP 注意
parent::__construct();
echo '1'.'<br />';
}
}
7. 魔術(shù)方法
__construct(): 構(gòu)造方法惧盹,new實(shí)例化時(shí)乳幸,自動(dòng)調(diào)用
__destruct(): 析構(gòu)方法,對(duì)象摧毀時(shí)自動(dòng)調(diào)用
__get(屬性名):當(dāng)讀取對(duì)象的一個(gè)不可見屬性時(shí)钧椰,自動(dòng)調(diào)用反惕,并返回值
不可見:未定義或者無權(quán)訪問時(shí)
__set(屬性名,屬性值):當(dāng)對(duì)一個(gè)不可見的屬性賦值時(shí)演侯,自動(dòng)調(diào)用
__isset(屬性名) : 當(dāng)用isset,或者empty判斷一個(gè)不可見的屬性時(shí)姿染,自動(dòng)調(diào)用
__unset(屬性名): 當(dāng)unset一個(gè)不可見屬性時(shí),自動(dòng)調(diào)用
<?php
class Human {
private $age = 9;
public $school = 'PKU';
public function __get($a) {
echo 'you want get my $' , $a , '<br />';
return 3;
}
public function __set($per , $value) {
echo 'you want to set my ' ,$per ,' to ' , $value , '<br />';
}
public function __isset($per) {
return true;
}
public function __unset($per) {
echo 'you want to unset my ' , $per;
}
}
$a= new Human();
echo $a->age;//=>you want get my $age 換行 3
echo $a->name;//=>you want get my $name 換行 3
$a->age='20';//=>you want to set my age to 20
$a->name='jjd';//=>you want to set my name to jjd
var_dump(isset($a->name));//=>bool(true)
var_dump(isset($a->age));//=>bool(true)
unset($a->name);//=>you want to unset my name
unset($a->age);//=>you want to unset my age
8. 魔術(shù)方法的作用
對(duì)于下面那個(gè)類來說秒际,外部可以隨意設(shè)置悬赏、添加、修改娄徊、刪除屬性闽颇,類本身失去了對(duì)屬性的控制權(quán)
class Foo {
}
$foo = new Foo();
$foo->age = 9;
print_r($foo); // Foo Object ( [age] => 9 )
需要做如下修改
class Bar {
public function __set($per , $value) {
//一般用于做些判斷,那些私有屬性可以刪除
echo '我想知道你想設(shè)置' , $per,'為' , $value , '<br />';
echo '但設(shè)不設(shè)置看我的心情<br />';
}
}
$bar = new Bar();
$bar->age = 9;
print_r($bar);//=>我想知道你想設(shè)置age為9
//但設(shè)不設(shè)置看我的心情
//Bar Object ( )
9. 自動(dòng)加載
其他文件中實(shí)例化某個(gè)類時(shí)寄锐,需要提前用require,include引入文件兵多,這樣類比較多尖啡,目錄也比較多,很麻煩剩膘,所以引入了自動(dòng)加載
思路:
聲明一個(gè)函數(shù)衅斩,并注冊(cè)為"自動(dòng)加載函數(shù)"。
當(dāng)系統(tǒng)發(fā)現(xiàn)某個(gè)類不存在時(shí)怠褐,會(huì)調(diào)用此函數(shù)畏梆,此函數(shù)中加載需要的類文件
//用于調(diào)用文件中的類$class時(shí)類名(所以類名和文件名要一致,這樣才能引進(jìn)對(duì)應(yīng)類)
function myLoad($class) {
require('./' . $class . '.php');
}
//定義了一個(gè)注冊(cè)函數(shù)奈懒,當(dāng)實(shí)例化的類不存在時(shí)去走注冊(cè)函數(shù)
spl_autoload_register('myLoad');
//實(shí)例化一個(gè)對(duì)象奠涌,檢測(cè)到本文件沒有,會(huì)跳到spl函數(shù)
new mysql();
10. 抽象類
類前面加上abstract就是抽象類 方法前面加上abstract就是抽象方法 抽象方法沒有方法體(沒有大括號(hào))
抽象類中也可以有已經(jīng)實(shí)現(xiàn)的方法(此方法必須是public)磷杏,但只要有一個(gè)抽象方法溜畅,此類就是抽象類
抽象類不能被實(shí)例化
當(dāng)抽象類被繼承時(shí),子類必須全部實(shí)現(xiàn)父類的抽象方法极祸,否則子類還是抽象類
語法如下:
abstract class aDB {
abstract public function getRow($sql);
abstract public function getAll($sql);
abstract public function Exec($sql);
}
class MySQL extends aDb {
}
抽象類的意義
在實(shí)際開發(fā)中慈格,因?yàn)闀r(shí)多人寫作,負(fù)責(zé)的地方不一樣贿肩,工作有先后或者爭(zhēng)議峦椰,這樣就可以在定義一個(gè)模板(抽象類),其中嚴(yán)格的規(guī)定方法名汰规,參數(shù)汤功,返回值,這樣就可以開始工作了溜哮。后期確定好之后在更改就可以了滔金。
11. 接口的概念
抽象類可以理解為‘類的模板’,接口則是‘方法’的模板茂嗓,主要用于描述通用的方法
定義和語法如下:
//定義幾個(gè)接口
interface flyer {
public function fly($oil , $height);
}
interface runer {
public function run($cicle , $dir);
}
interface water {
public function swim($dir);
}
//聲明一個(gè)類餐茵,想用一些通用的方法,獲取上面部分或全部接口來使用
//只要調(diào)用了接口述吸,就要全部實(shí)現(xiàn)其方法
class Super implements flyer , runer , water {
public function fly($oil , $height) {
echo 'I am flying';
}
public function run($cicle , $dir) {
echo 'I am flying';
}
public function swim($dir) {
echo 'I am flying';
}
}
$s = new Super();
12. 錯(cuò)誤異常(一般在不該出錯(cuò)的時(shí)候用忿族,如 連接數(shù)據(jù)庫)
function t1() {
if(rand(1,10) > 5) {
throw new Exception("我", 1);
} else {
return t2();
}
}
function t2() {
if(rand(1,10) > 5) {
throw new Exception("你", 2);
} else {
return t3();
}
}
function t3() {
if(rand(1,10) > 5) {
throw new Exception("他", 3);
} else {
return true;
}
}
//$e可以隨便寫,他是一個(gè)對(duì)象蝌矛,可以打印下看看
try {
var_dump(t1());
} catch(Exception $e) {
echo '文件:' , $e->getFile() , '<br />';
echo '出錯(cuò)行:' , $e->getLine() , '<br />';
echo '錯(cuò)誤信息' , $e->getMessage() , '<br />';
}
13. 命名空間
多人開發(fā)時(shí)道批,函數(shù)名很容易重復(fù),引入匿名空間可以解決 namespace 的聲明不許再可執(zhí)行代碼之前
namespace 聲明后入撒,其后的類隆豹,函數(shù),都被封鎖到命名空間中
require/include其他帶有命名空間的頁面茅逮,自身的空間并沒有被影響
//test.php
<?php
namespace zixueit;
class Mysqli {
public $test = 'my-mysqli';
}
//test1.php
require('./test.php');
//下面方法是錯(cuò)誤的
//print_r(new Mysqli());
//可以訪問兩種效果是一樣的
print_r(new \zixueit\Mysqli());
use \zixueit\Mysqli;
print_r(new Mysqli());
//輸出:zixueit\Mysqli Object ( [test] => my-mysqli
)
//當(dāng)兩個(gè)文件的類名一樣時(shí)璃赡,可以給引入的取個(gè)別名
use \zixueit\Mysqli as a;
print_r(new a());//輸出結(jié)果也一樣
14. 延遲綁定
class Par {
public static function who() {
echo 'Par ~~~';
}
public static function test() {
echo self::who();
}
}
class Son extends Par {
public static function who() {
echo 'Son ~~~';
}
}
Son::test(); // Par ~~~
當(dāng)繼承父類時(shí)判哥,因?yàn)樽宇恡est方法訪問的是self,為本類(父類)的who方法碉考,所以子類繼承之后會(huì)訪問父類的who塌计,想要訪問子類自己的who,則如下修改:
class Par {
public static function who() {
echo 'Par ~~~';
}
public static function test() {
//此時(shí)豆励,哪個(gè)類對(duì)用test方法夺荒,static就是那個(gè)對(duì)象
echo static::who();
}
}
class Son extends Par {
public static function who() {
echo 'Son ~~~';
}
}
Son::test(); // Son ~~~
15. 超載的static(static的使用)
- 函數(shù)內(nèi)聲明靜態(tài)變量用(聲明之后下次訪問會(huì)保留上次的值)
function t() {
static $age = 1;
$age +=1;
echo $age , '<br />';
}
t();//2
t();//3
- 聲明類的靜態(tài)屬性和靜態(tài)方法時(shí)用
class Human {
public static $leg = 99;
public static function cry() {
echo '55';
}
}
echo Human::$leg , '<br />';
- 延遲綁定
class Par {
public static function Model() {
echo __CLASS__ , '<br />';
echo get_called_class() , '<br />';
}
//下面這個(gè)static::瞒渠,會(huì)把調(diào)用Model的上下文切換運(yùn)行時(shí)的調(diào)用類良蒸,而非定義時(shí)
public static function save() {
static::Model();
}
}
class Son extends Par {
public static function Model() {
echo __CLASS__ , '<br />';
echo get_called_class() , '<br />';
}
}
Son::save(); // Son,Son