屬性和方法的訪問控制(可見標識):public
任何地方private
類自身protected
類自身,自子類及自父類php
this
能夠理解爲這個類的一個實例數組
self
表明類自己函數
實例化時就會自動執行public function __construct() {}
ui
當對象對銷燬時自動執行public function __destruct(){}
this
定義合不可改變spa
const ONE = 1
const TWO = self::ONE + 1;
code
能夠在類外部調用Class::Two
對象
parent
表明父類public function __construct(){ parent::__construct();}
繼承
final class Dad(){}
加到類定義前面表示Dad類不想被繼承接口
class Dad(){ final public function run(){} // 加到方法聲明前面,表示方法不想被子類重寫 }
namespace
必須放在代碼文件的第一行
受命名空間影響的類型:類(包括抽像類,traits)、接口、函數和常量。
當沒有使用namespace
關鍵字指定命名空間時,當前腳本是存在於全局命名空間的。用\
表示。\Class1
類全在指定的命名空間去查找,沒找到則拋出錯誤。
函數與常量,在指定命名空間查找,沒找到則到全局命名空間查找
,還沒打到則拋錯。
ns1\ns2\fn()
define
定義的常量是全局的,不受命名空間影響。const
定義的常量受命名空間影響。
namespace ns1\ns2; const ONE = 1; echo ns1\ns2\ONE;
用use
導入命名空間下的類use ns1\ns2\class1;
用as
重命名導入的類use ns1\ns2\class1 as class2;
use function ns1\ns2\fn as fn1;
use const ns1\ns2\ONE;
function __autoload($className){ require $className . '.php';}
spl_autoload_register(function($className){ require $className . '.php'; });
function test($className){ require $className . '.php'; } spl_autoload_register('test');
class Momo { function autoload($className) { require $className . '.php'; } } spl_autoload_register([new Momo, 'autoload']);
聲明靜態屬性和靜態方法,不通過實例化,經過類名便可調用。
class Person() { public static $hand = '手'; public static function run() { echo 'running...'; } } echo Person::$hand; Person::run();
類內部調用靜態屬性和靜態方法用self
關鍵字
echo self::$hand;
self::run();
調用父類的靜態屬性和靜態方法用parent
關鍵字
echo parent::$hand;
parent::run();
class A { public static function who() { echo 'A類的who方法'; } public static function test1() { self::who(); } public static function test2() { static::who(); } } class B extends A { public static function who() { echo 'B類的who方法'; } } B::test1(); // test1內部用的self,調用的是自身(A類)的靜態方法 B::test2(); // 後期綁定。內部用static,根據後期的調用環境肯定,調用的是B類的靜態方法
class Test { private $name = ''; public function __set($var, $val) { // 對$val進行數據處理 $this->$var = $val; } } $test = new Test(); $test->name = 'tom'; // 賦值tom
class Test { private $name = 'jack'; public function __get($var) { return $this->$var; } } $test = new Test(); echo $test->name; // jack
用於檢測私有屬性是否存在
class Test { private $name = 'mary'; public function __isset($var) { return isset($this->$var); } } $test = new Test(); var_dump($test->name); // 若是不設置__isset,返回false,設置後返回true
用於刪除私有屬性
class Test { private $name = 'Levi'; public function __unset($var) { unset() } } $test = new Test; unset($test->name); // 會觸發__unset
避免調用一個不存在的方法時產生錯誤,當調用的方法不存在時,__call
方法會自動調用
class Test { public function __call($fn_name, $fn_arguments) { echo $fn_name; print_r($fn_arguments); } } $test = new Test(); $test->go(1, 'ok'); // 自動調用`__call`方法,打印出函數名和參數數組
同__call
相似
避免調用一個不存在的靜態方法
class Test { public static function __callStatic($fn_name, $fn_arguments) { echo $fn_name; print_r($fn_arguments); } } // `__callStatic` 必須聲明爲靜態方法 Test::go(1, 'ok');
當對象以函數的形式調用的時候,自動調用__invoke
方法
class Test { public function __invoke($args) { return $args; } } $test = new Test(); $test('go.....'); // 運行__invoke
當打印對象是會調用__toString
方法
class Test { public function __toString() { return 'Hello world!'; } } $test = new Test; echo $test; // 輸出 Hello world!
比較省內存,對象的拷貝默認是淺拷貝。
$a = new Test(); $b = $a; // 淺拷貝。傳址。改變$b。$a也會改變。
對象的複製是淺拷貝的。傳址。
普通變量的拷貝是深拷貝的。傳值。
$a = new Test(); $b = clone $a; // 深拷貝。改變$b,不會改變$a。
當使用clone
關鍵字時,自動調用__clone
方法
class Test { public $obj = null; public function __clone() { $this->obj = clone $this->obj; } } class Person { public $sex = 0; } $a = new Test; $a->obj = new Person; $b = clone $a; // 觸發`__clone` 對obj進行深拷貝 $b->obj->sex = 1; // $b中的obj對象改變了。而$a中的obj對象沒變。
class A { public function go() { echo 'go .....'; } } function test(A $a) { $a->go(); } test(new A());
單繼承語言PHP的代碼複用機制。
Trait Bt { public function atest() { echo 'Hello '; } public function btest() { echo 'world'; } public function ab() { $this->atest(); $this->btest(); } } class Test { use Bt; // 使用Bt Trait,便擁有了Bt全部的方法 } $test = new Test; $test->ab();
繼承多個Trait
Trait A { public $name = 'tom'; public function a() { echo 'Hello '; } } Trait B { public function b() { echo 'world '; } } class Test { use A,B; public function c() { echo $this->name; } } $test = new Test; $test->a(); $test->b(); $test->c(); // Hello world tom
Trait 支持嵌套
Trait A{} Trait B{} Trait C { use A,B; } Class Test { use C; }
接口是類的模板。在接口中只定義須要實現的空方法,這些方法在接口中不作具體實現。
接口是不能被實例化的。
Interface Person { public function eat(); public function sleep(); } class man implements Person { public function eat() { echo 'eating...'; } public function sleep() { echo 'sleeping...'; } } class L { public static function factory(Person $user) // 用接口做類型約束 { return $user; } } $user = L::factory(new Man()); $user->eat(); $user->sleep();
接口能夠繼承接口。
接口能夠繼承多個接口。
接口能夠使用常量,叫接口常量,和類的常量使用方法相同
Interface Ia { const ONE = 1; public function eat(); } Interface Ib { public function sleep(); } Interface AB extends Ia,Ib {} // class Test implements Ia,Ib 類能夠同時繼承多個接口 class Test implements AB { public function eat() { echo 'eating...'; } public function sleep() { echo 'sleeping...'; } } $test = new Test; $test->eat(); $test->sleep(); echo Ia::ONE; // 使用接口常量
抽象類不能被實例化。
若是至少有一個方法被聲明爲抽象的,那麼這個類必須被聲明爲抽象的。
抽象方法只能聲明,不能有具體功能實現。
抽象類能夠有被實現的的方法。
繼承抽象類,子類必須實現父類中全部的抽象方法。
這些方法的訪問控制必須和父類同樣,或者更寬鬆,不能比父類更嚴格。
方法的調用方式也必須匹配。類型和參數數量必須一致,但子類能夠定義父類中不存在的可選參數。
abstract AB { public function run() { echo 'running...'; } abstract public function eat(); abstract public function sleep(); } class Test extends AB { public function eat() { echo 'eating...'; } public function sleep($time = '21:00 PM') // 能夠定義父類方法中不存在的可選參數 { echo 'sleep @ ' . $time; } }
只能被實例化一次,節省內存空間
class Test { private static $instance = null; private function __constrct() {} private function __clone() {} public static function getInstance() { if (!(self::instance instanceof self)) { self::instance = new self(); } return self::instance; } } $test = Test::getInstance(); // 屢次調用也只是實例化一次
Interface CacheI { public function set($key, $value); public function get($key); public function delete($key); } class Memcache implements CacheI { public function set($key, $value){} public function get($key){} public function delete($ke){} } class Redis implements CacheI { public function set($key, $value){} public function get($key){} public function delete($ke){} } class Cache { public static function factory() { return new Memcache(); // 這裏能夠是繼承了CacheI接口的任何類,好比Redis } } $cache = Cache::factory(); $cache->set('name', 'tom'); $cache->get('name'); $cache->delete('name');