## 面向對象
類:現實世界或思維世界中的實體在計算機中的反映,它將數據以及這些數據上的操作封裝在一起。比如人類、動物類
對象: 具有類類型的變量。比如人類中的張三這就是一個對象。他有人類的特性,比如說話寫字等。
屬性:類型的特征 比如人的名字、年齡、身高都是人的特征屬性。
方法:方法是將一些操作封裝起來的過程。類似函數。
繼承:從父類那獲得特征。比如人從父親那繼承了父親的姓名。
### class (類)
每個類的定義都以關鍵字?*class*?開頭,后面跟著類名,后面跟著一對花括號,里面包含有類的屬性與方法的定義
類名是非php保留字以外的合法的標簽。合法的類名和變量一樣。字母、下劃線開頭,后面跟任意字母或數字。
自 PHP 5.5 起,關鍵詞?*class*?也可用于類名的解析。使用?*ClassName::class*?你可以獲取一個字符串
```php
class Person {
public $name;
public $age;
public function say(){
echo "hello";
}
}
echo Person::class;//Person 如果帶命名空間。則會加上命名空間
```
要創建一個對象。使用new關鍵字
```php
$zhang = new Person();
$zhang->name = '張三';
```
### extends (繼承)
一個類可以在聲明中用?*extends*?關鍵字繼承另一個類的方法和屬性。PHP不支持多重繼承,一個類只能繼承一個基類。
被繼承的方法和屬性可以通過用同樣的名字重新聲明被覆蓋。如果父類的方法使用了final。則不會被覆蓋。
當覆蓋方法時,參數必須保持一致否則 PHP 將發出?**E_STRICT**?級別的錯誤信息。但構造函數例外,構造函數可在被覆蓋時使用不同的參數
```php
class Boy extends Person {
}
```
### 類常量
在類中始終保持不變的值定義為常量。在定義和使用常量的時候不需要使用?$?符號
類常量是一個定值。類常量使用const 定義。訪問的時候使用**self::**訪問類常量
```php
class C{
const PI = 3.1415926;
public function test(){
echo self::PI;
}
}
```
### 自動加載
使用自動加載可以讓我們不用一個個去include 類文件
自動加載不可用于 PHP 的 CLI
```php
spl_autoload_register(function($class){
require $class.".php";
})
```
### 構造函數、析構函數
構造函數在對象創建的時候,會被調用。適合初始化工作。
如果子類中定義了構造函數則不會隱式調用其父類的構造函數。要執行父類的構造函數,需要在子類的構造函數中調用**parent::__construct()**
析構函數在到某個對象的所有引用都被刪除或者當對象被顯式銷毀時執行
試圖在析構函數(在腳本終止時被調用)中拋出一個異常會導致致命錯誤。
```php
class P{
public function __construct(){
echo "construct";
}
public function __destruct(){
echo "destruct";
}
}
$p = new P();// construct;
unset($p);//destruct;
```
### 訪問控制
對屬性或方法的訪問控制,是通過在前面添加關鍵字?*public*(公有),*protected*(受保護)或?*private*(私有)來實現的。
public 修飾的 可以在任何地方訪問到
protected修飾的只能在子類或該類中訪問
private修飾的只能在該類中訪問。
```php
class A{
public $name = 'a';
protected $age = 10;
private $money = 100;
}
class B extends A{
public function test(){
echo $this->age;//a
}
public function testPrivate(){
echo $this->money;
}
}
$b = new B();
echo $b->name;//a
echo $b->test();//10
# 不可訪問
echo $b->age;//error;
#子類不能訪問
echo $b->testPrivate();//error
```
### 范圍解析操作符(::)
范圍解析操作符(也可稱作 Paamayim Nekudotayim)或者更簡單地說是一對冒號,可以用于訪問靜態成員,類常量。還可以用于覆蓋類中的屬性和方法。
self,parent?和?static?這三個特殊的關鍵字是用于在類定義的內部對其屬性或方法進行訪問的
當一個子類覆蓋其父類中的方法時,PHP 不會調用父類中已被覆蓋的方法。是否調用父類的方法取決于子類。使用self調用父類,使用$this 調用本類。
```php
class A{
public $name = 'a';
protected $age = 10;
private $money = 100;
}
class B extends A{
public static $s = 's';
const PI = 111;
public function test(){
echo parent::age;// 10
}
public static function testStatic(){
echo self::$s;
}
public function testConst(){
echo self::PI;
}
public function testPrivate(){
echo $this->money;
}
}
# self 和 $this
class ParentClass {
function test() {
self::who(); // will output 'parent'
$this->who(); // will output 'child'
}
function who() {
echo 'parent';
}
}
class ChildClass extends ParentClass {
function who() {
echo 'child';
}
}
$obj = new ChildClass();
$obj->test();//
```
### static 靜態關鍵字
聲明類屬性或方法為靜態,就可以不實例化類而直接訪問。靜態屬性不能通過一個類已實例化的對象來訪問(但靜態方法可以)
靜態屬性不可以由對象通過 -> 操作符來訪問。靜態屬性只能被初始化為文字或常量。靜態屬性不隨著對象的銷毀而銷毀。
```php
class P{
$a = "world";
public static function test(){
echo "hello".self::$a;
}
}
p::test();
```
### 抽象類
從具體事物抽出、概括出它們共同的方面、本質屬性與關系等,而將個別的、非本質的方面、屬性與關系舍棄,這種思維過程,稱為抽象。
php中如果一個類的方法被定義為抽象,那么該類就是抽象類。抽象類不能被實例化。只能被子類繼承,子類必須實現全部的抽象方法,并且訪問修飾必須和父類相同或者更寬松。參數必須一致。
```php
abstract class AbstractClass {
abstract public function test();
}
class Son extends AbstractClass{
public function test(){
echo "test";
}
}
```
### 對象接口
接口泛指實體把自己提供給外界的一種[抽象化](可以為另一實體),用以由內部操作分離出外部溝通方法,使其能被內部修改而不影響外界其他實體與其交互的方式。
使用接口不需要實現哪些方法,只需要定義這些方法。具體的實現由類去實現。
接口通過**interface**定義。實現接口通過**implements**。接口可以被繼承
接口中也可以定義常量。但是不能定義屬性。接口允許多繼承
```php
interface Iter{
public function test();
}
class ClassT implements Iter{
public function test(){
}
}
interface Iter2 extends Iter {
public function test2();
}
class ClassT2 implements Iter2 {
public function test(){}
public function test2(){}
}
#多繼承
interface Iter3 extends Iter1,Iter2{}
/**
* An example of duck typing in PHP
*/
interface CanFly {
public function fly();
}
interface CanSwim {
public function swim();
}
class Bird {
public function info() {
echo "I am a {$this->name}\n";
echo "I am an bird\n";
}
}
/**
* some implementations of birds
*/
class Dove extends Bird implements CanFly {
var $name = "Dove";
public function fly() {
echo "I fly\n";
}
}
class Penguin extends Bird implements CanSwim {
var $name = "Penguin";
public function swim() {
echo "I swim\n";
}
}
class Duck extends Bird implements CanFly, CanSwim {
var $name = "Duck";
public function fly() {
echo "I fly\n";
}
public function swim() {
echo "I swim\n";
}
}
/**
* a simple function to describe a bird
*/
function describe($bird) {
if ($bird instanceof Bird) {
$bird->info();
if ($bird instanceof CanFly) {
$bird->fly();
}
if ($bird instanceof CanSwim) {
$bird->swim();
}
} else {
die("This is not a bird. I cannot describe it.");
}
}
// describe these birds please
describe(new Penguin);
echo "---\n";
describe(new Dove);
echo "---\n";
describe(new Duck);
```
### Trait
Trait 是為類似 PHP 的單繼承語言而準備的一種代碼復用機制。Trait 為了減少單繼承語言的限制.無法通過 trait 自身來實例化。它為傳統繼承增加了水平特性的組合
#### trait定義
```php
trait t{
public function test(){}
}
# 使用
class Test{
use t;
public function test2{
$this->test();
}
}
```
#### 優先級
從基類繼承的成員會被 trait 插入的成員所覆蓋。優先順序是來自當前類的成員覆蓋了 trait 的方法,而 trait 則覆蓋了被繼承的方法。
```php
class Base {
public function say(){
echo "base";
}
}
trait Test{
public function say(){
echo "trait";
}
}
class Son extends Base {
use Test;
public function test(){
$this->say();
}
}
$s = new Son();
$s->test();//trait
# 在子類中重寫say。則調用子類的say方法
public function say(){
echo "son";
}
```
#### 多個trait組合
通過逗號分隔,在 use 聲明列出多個 trait,可以都插入到一個類中
```php
trait Hello {
public function sayHello() {
echo 'Hello ';
}
}
trait World {
public function sayWorld() {
echo 'World';
}
}
class MyHelloWorld {
use Hello, World;
public function sayExclamationMark() {
echo '!';
}
}
```
#### 沖突的解決
如果多個trait中。都有同名的方法,則會產生沖突,沖突會產生一個致命的錯誤。
為了解決多個 trait 在同一個類中的命名沖突,需要使用?*insteadof*?操作符來明確指定使用沖突方法中的哪一個
*as*?操作符可以 為某個方法引入別名
```php
trait A {
public function smallTalk() {
echo 'a';
}
public function bigTalk() {
echo 'A';
}
}
trait B {
public function smallTalk() {
echo 'b';
}
public function bigTalk() {
echo 'B';
}
}
class Talker {
use A, B {
B::smallTalk insteadof A;
A::bigTalk insteadof B;
}
}
class Aliased_Talker {
use A, B {
B::smallTalk insteadof A;
A::bigTalk insteadof B;
B::bigTalk as talk;
}
}
```
#### 使用as修改訪問控制
```php
class Base {
public function say(){
echo "base";
}
}
trait Test{
public function say(){
echo "trait";
}
}
class Son extends Base {
use Test {say as private say2;}
public function say(){
echo "son";
}
}
$s = new Son();
$s->say2();//error
```
#### 使用多個trait組合
```php
trait A{}
trait B{}
trait C{use A,B;}
```
#### trait抽象成員方法
為了對使用的類施加強制要求,trait 支持抽象方法的使用
```php
trait T{
abstract public function test();
}
class Test{
use T;
public function test(){}
}
```
#### trait 靜態方法
```php
trait T{
public static function test() {};
}
class Test{
use T;
}
Test::test();
```
#### trait定義屬性
Trait 定義了一個屬性后,類就不能定義同樣名稱的屬性
```php
trait PropertiesTrait {
public $same = true;
public $different = false;
}
class PropertiesExample {
use PropertiesTrait;
public $same = true; // PHP 7.0.0 后沒問題,之前版本是 E_STRICT 提醒
public $different = true; // 致命錯誤
```
### 匿名類
**PHP 7** 開始支持匿名類。 匿名類很有用,可以創建一次性的簡單對象
匿名類被嵌套進普通 Class 后,不能訪問這個外部類(Outer class)的 private(私有)、protected(受保護)方法或者屬性。 為了訪問外部類(Outer class)protected 屬性或方法,匿名類可以 extend(擴展)此外部類。 為了使用外部類(Outer class)的 private 屬性,必須通過構造器傳進來.
```php
$a = new class {
public function test(){
echo "test";
}
};
$a->test();
```
### 重寫、重載
override是重寫(覆蓋)了一個方法,以實現不同的功能。一般是用于子類在繼承父類時,重寫(重新實現)父類中的方法。
**重寫(覆蓋)的規則**:
?? 1、重寫方法的參數列表必須完全與被重寫的方法的相同,否則不能稱其為重寫而是重載.
?? 2、重寫方法的訪問修飾符一定要大于被重寫方法的訪問修飾符(public>protected>default>private)。
?? 3、重寫的方法的返回值必須和被重寫的方法的返回一致;
?? 4、重寫的方法所拋出的異常必須和被重寫方法的所拋出的異常一致,或者是其子類;
?? 5、被重寫的方法不能為**private**,否則在其子類中只是新定義了一個方法,并沒有對其進行重寫
6、靜態方法不能被重寫為非靜態的方法(會編譯出錯)。
overload是重載,一般是用于在一個類內實現若干重載的方法,這些方法的名稱相同而參數形式不同。
**重載的規則**:
?? 1、在使用重載時只能通過相同的方法名、不同的參數形式實現。不同的參數類型可以是不同的參數類型,不同的參數個數,不同的參數順序(參數類型必須不一樣);
?? 2、不能通過訪問權限、返回類型、拋出的異常進行重載;
?? 3、方法的異常類型和數目不會對重載造成影響;
PHP所提供的"重載"(overloading)是指動態地"創建"類屬性和方法。我們是通過魔術方法(magic methods)來實現的。
```php
class A{
public function test(){
echo "11";
}
}
class B extends A{
#重寫父類的方法
public function test(){
echo "22";
}
}
class C{
public function __call($name,$args) {
echo $name;
}
public function __callStatic($name, $arguments){}
}
```
### 多態
多態:同一操作作用于不同的對象,可以有不同的解釋,產生不同的執行結果。在運行時,可以通過指向基類的指針,來調用實現派生類中的方法。
```php
abstract class animal{
abstract function fun();
}
class cat extends animal{
function fun(){
echo "cat say miaomiao...";
}
}
class dog extends animal{
function fun(){
echo "dog say wangwang...";
}
}
function work($obj){
if($obj instanceof animal){
$obj -> fun();
}else{
echo "no function";
}
}
work(new dog());
work(new cat());
```
### 遍歷對象
遍歷對象可以使用foreach遍歷可見屬性。或者實現iterator接口
```php
class MyClass
{
public $var1 = 'value 1';
public $var2 = 'value 2';
public $var3 = 'value 3';
protected $protected = 'protected var';
private $private = 'private var';
}
$c = new MyClass();
foreach ($c as $key=>$v) {
echo $key."=>"$v;
}
```
### 魔術方法
- __construct 初始化調用
- __desturct 對象銷毀時調用
- __call 訪問一個不存在的方法的時候調用
- __callStatic 訪問一個不存在的靜態方法調用
- __get() 訪問一個不存在的屬性調用
- __set() 修改一個不存在的屬性調用
- __isset() 使用isset判斷一個高屬性的時候調用
- __toString() 當一個對象以一個字符串返回時候觸發調用
- __invoke()當把一個對象當初函數去調用的時候 觸發
### final
final 最終的,如果一個類被定位成final 這個類不能被繼承。如果一個方法被定義一個final。這個方法不能被覆蓋。
final不能修飾屬性。
```php
class A{
final public function test(){}
}
Class B extends A{
public function test(){ //error
}
}
```
### 對象復制、對象比較
對象復制可以通過 **clone** 關鍵字來完成
當對象被復制后,PHP 5 會對對象的所有屬性執行一個淺復制(shallow copy)。所有的引用屬性 仍然會是一個指向原來的變量的引用。
```php
class A{
public $name = "hello";
}
$a = new A();
$b = clone $a;
```
當使用比較運算符(*==*)比較兩個對象變量時,比較的原則是:如果兩個對象的屬性和屬性值 都相等,而且兩個對象是同一個類的實例,那么這兩個對象變量相等。
而如果使用全等運算符(*===*),這兩個對象變量一定要指向某個類的同一個實例(即同一個對象)
### 類型約束
函數的參數可以指定必須為對象(在函數原型里面指定類的名字),接口,數組
```php
function Test(A $a){}
```
### 后期靜態綁定
“后期綁定”的意思是說,*static::*?不再被解析為定義當前方法所在的類,而是在實際運行時計算的。也可以稱之為“靜態綁定”,因為它可以用于(但不限于)靜態方法的調用
**self的限制**
使用?*self::*?或者?*__CLASS__*?對當前類的靜態引用,取決于定義當前方法所在的類
```php
class A {
public static function who() {
echo __CLASS__;
}
public static function test() {
self::who();
}
}
class B extends A {
public static function who() {
echo __CLASS__;
}
}//
B::test();//A
#靜態綁定語法
class A {
public static function who() {
echo __CLASS__;
}
public static function test() {
static::who();
}
}
class B extends A {
public static function who() {
echo __CLASS__;
}
}//
B::test();//B
## 實現ar model
class Model
{
public static function find()
{
echo static::$name;
}
}
class Product extends Model
{
protected static $name = 'Product';
}
Product::find();
```
### 對象和引用
> PHP 的引用是別名,就是兩個不同的變量名字指向相同的內容。在 PHP 5,一個對象變量已經不再保存整個對象的值。只是保存一個標識符來訪問真正的對象內容。 當對象作為參數傳遞,作為結果返回,或者賦值給另外一個變量,另外一個變量跟原來的不是引用的關系,只是他們都保存著同一個標識符的拷貝,這個標識符指向同一個對象的真正內容。
```php
class A {
public $foo = 1;
}
$a = new A;
$b = $a; // $a ,$b都是同一個標識符的拷貝
// ($a) = ($b) = <id>
$b->foo = 2;
echo $a->foo."\n";
```
### 對象序列化
在會話中存儲對象。使用serialize序列化。
- PC
- IO模型
- Inode介紹
- Linux
- Linux基本操作命令
- Linux網絡相關命令
- Crontab計劃任務
- Shell
- Sed命令
- Awk命令
- LAMP/LNMP
- PHP
- 基本語法
- 面向對象
- 錯誤和異常處理
- 命名空間
- PHP7
- 正則表達式
- Hashtable
- 變量的內部實現
- PHP-FPM
- PHP運行原理
- swoole
- mysql
- SQL標準
- mysql三范式
- 存儲引擎
- Mysql事務
- Mysql索引
- Mysql優化
- Explain
- MySQL索引原理及慢查詢優化
- MongoDb
- 計算機網絡
- IP協議
- TCP(傳輸控制協議)
- UDP(用戶數據報協議)
- HTTP 協議
- HTTPS
- HTTP的基本優化
- Websocket協議
- 版本控制器
- Git
- Svn
- 數據結構
- 數組
- 鏈表
- 算法