php.類與對象

訪問控制

屬性和方法的訪問控制(可見標識):
public 任何地方
private 類自身
protected 類自身,自子類及自父類php

this

this 能夠理解爲這個類的一個實例數組

self

self 表明類自己函數

__construct

實例化時就會自動執行
public function __construct() {}ui

__destruct

當對象對銷燬時自動執行
public function __destruct(){}this

類常量

定義合不可改變spa

const ONE = 1
const TWO = self::ONE + 1;code

能夠在類外部調用
Class::Two對象

parent

parent表明父類
public function __construct(){ parent::__construct();}繼承

final

final class Dad(){} 加到類定義前面表示Dad類不想被繼承接口

class Dad(){
    final public function run(){}  // 加到方法聲明前面,表示方法不想被子類重寫
}

namespace

namespace必須放在代碼文件的第一行
受命名空間影響的類型:類(包括抽像類,traits)、接口、函數和常量。
當沒有使用namespace關鍵字指定命名空間時,當前腳本是存在於全局命名空間的。用\表示。\Class1
類全在指定的命名空間去查找,沒找到則拋出錯誤。
函數與常量,在指定命名空間查找,沒找到則到全局命名空間查找,還沒打到則拋錯。

函數

ns1\ns2\fn()

常量

define定義的常量是全局的,不受命名空間影響。
const定義的常量受命名空間影響。

namespace ns1\ns2;
const ONE = 1;

echo ns1\ns2\ONE;

use

導入類

use導入命名空間下的類
use ns1\ns2\class1;

as重命名導入的類
use ns1\ns2\class1 as class2;

導入函數

use function ns1\ns2\fn as fn1;

導入常量

use const ns1\ns2\ONE;

自動加載

__autoload

function __autoload($className){ require $className . '.php';}

spl_autoload_register

傳匿名函數

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']);

static

聲明靜態屬性和靜態方法,不通過實例化,經過類名便可調用。

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類的靜態方法

魔術方法

__set

class Test
{
    private $name = '';
    
    public function __set($var, $val)
    {
        //     對$val進行數據處理
        $this->$var = $val;
    }
}

$test = new Test();
$test->name = 'tom';    // 賦值tom

__get

class Test
{
    private $name = 'jack';
    public function __get($var)
    {
        return $this->$var;
    }
}

$test = new Test();
echo $test->name;    // jack

__isset

用於檢測私有屬性是否存在

class Test
{
    private $name = 'mary';
    
    public function __isset($var)
    {
        return isset($this->$var);
    }
}
$test = new Test();
var_dump($test->name);    // 若是不設置__isset,返回false,設置後返回true

__unset

用於刪除私有屬性

class Test
{
    private $name = 'Levi';
   public function __unset($var)
   {
           unset()
   }
}
$test = new Test;
unset($test->name);        // 會觸發__unset

__call

避免調用一個不存在的方法時產生錯誤,當調用的方法不存在時,__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`方法,打印出函數名和參數數組

__callStatic

__call相似
避免調用一個不存在的靜態方法

class Test
{
    public static function __callStatic($fn_name, $fn_arguments)
    {
        echo $fn_name;
        print_r($fn_arguments);
    }
}

// `__callStatic` 必須聲明爲靜態方法
Test::go(1, 'ok');

__invoke

當對象以函數的形式調用的時候,自動調用__invoke方法

class Test
{
    public function __invoke($args)
    {
        return $args;
    }
}
$test = new Test();
$test('go.....');    // 運行__invoke

__toString

當打印對象是會調用__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關鍵字時,自動調用__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());

Trait

單繼承語言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

接口是類的模板。在接口中只定義須要實現的空方法,這些方法在接口中不作具體實現。
接口是不能被實例化的。

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

抽象類不能被實例化。
若是至少有一個方法被聲明爲抽象的,那麼這個類必須被聲明爲抽象的。
抽象方法只能聲明,不能有具體功能實現。
抽象類能夠有被實現的的方法。

繼承抽象類,子類必須實現父類中全部的抽象方法。
這些方法的訪問控制必須和父類同樣,或者更寬鬆,不能比父類更嚴格。
方法的調用方式也必須匹配。類型和參數數量必須一致,但子類能夠定義父類中不存在的可選參數。

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');
相關文章
相關標籤/搜索