php面向對象我的濃縮總結和實例

大概1年前我總結過,可是那時候太菜,如今我又來總結了。 (本文是總結,不是入門,剛學oop的不適合看,基礎寫的比較省略。)php


0.思路

其實oop編程發展到如今,知識點不少,並且很雜,好比static就很亂,很容易混淆,我本身這麼分類:編程

  • 1.類和對象(建立類和對象的基本概念)
  • 2.層級組織及其衍生(完善和加強類,建立層級,便於組織和複用代碼)
  • 3.其餘工具和特性(各個語言都有的攔截器,序列化,php有的魔術方法等雜項)

1.類和對象

1.1類和對象的概念

類和對象是模擬現實中,一羣類似的物體,以及他們的抽象模板的關係,在編程中便於將方法(功能)和屬性(數據)組織到一塊兒,作到封裝,解耦,提升代碼的健壯性和複用性。 是一個很是重要的概念發明。bash

類和對象的基本概念一言難盡,總結:app

  • 類的由屬性和方法組成
  • 屬性和方法能夠調用
  • 類能夠實例化(new)出對象

1.2可見性

屬性和方法,都有三種可見性,分別用三個單詞去修飾函數

在類的外部可訪問 子類可訪問
public Y Y
protected N Y
private N N

1.3static做用域

類由屬性和方法組成,屬性和方法能夠調用,一個類實例化成多個對象後,每一個對象都有本身的屬性和方法,並且調用一樣的方法後結果不必定同樣,這叫多態。工具

然而屬性和方法不必定要實例化後才能調用,定義爲static的屬性和方法就是直接能夠調用,無需實例化。oop

我這麼理解,類是一個特殊的做用域,就當成一個特殊的對象,他持有靜態屬性和靜態方法,對象也能夠調用靜態方法,可是類不能調用非靜態方法。測試

對象改變靜態屬性的值後,當對象銷燬了,靜態屬性的值還在,由於他屬於類。ui

1.4自動加載

使用類前必須定義類,當前文件沒有這個類,就要include,當應用變大,就會很難搞。 就要用到自動加載。this

自動加載就是依靠spl_autoload_register()實現,參數是一個函數,當找不到使用的類的時候,就會將類名做爲參數傳入註冊的函數。

<?php
spl_autoload_register(function($class_name){
    require_once 'www/app/lib/'.$calss_name.'.php';
})
複製代碼

1.5構造函數

構造函數是最重要的一個魔術方法,因此提早單說。

2.層級設計及其衍生

發明類和對象的關係已經很厲害了,可是還不夠,爲了處理更加複雜的關係,出現了對象層級。

一個對象能夠繼承另外一個對象,這樣能夠更好得組織代碼和複用代碼。而後還有抽象類,接口和trait都是oop中組織和複用代碼的工具。

2.1繼承和重載

  • 一個對象能夠繼承另外一個對象,這樣他就具備了父對象的屬性和方法
  • 子對象能夠覆蓋父對象的方法
  • 調用時優先在子對象尋找屬性和方法,沒有就去父類尋找
  • 被final修飾的屬性和方法沒法重載

2.2抽象類 接口 trait

  • 抽象類的代碼是側重規範性而非實現功能,跟僞代碼有點像,他定義要實現哪些函數,可是不寫具體實現。
  • 接口跟抽象類很像,可是抽象類只能單繼承,接口能夠多繼承。
  • triat則是代碼片斷的複用。

一言難盡,直接說重點

是否多繼承 代碼是有功能性的仍是規範性的
N 功能
抽象類 N 規範(主要)和功能
接口 Y 規範
trait Y 功能(主要)和規範

注意

  • 1.抽象類
    • 只要類中有抽象方法,就必須定義爲抽象類,同時裏面能夠有非抽象方法
  • 2.接口
    • 接口的的方法都是public的,而且是沒有內容的, 接口能夠有常量
    • 接口還能夠繼承接口,擴展
  • 3.trait
    • 能夠有屬性、方法、能夠是靜態的,
    • 甚至能夠寫抽象方法,
    • trait還能夠包含trait,
    • 導入trait的時候還能更改裏面方法的可見性

2.3各類組合下的調用屬性和方法

靜態非靜態*內外部+常量

class ClassA{
	//屬性
	public  $var1 = 1;
	//靜態屬性 靜態就是歸類管,不歸對象管
	public static $var2 = 2;
	//常量 常量不可更改 訪問方式相似靜態
	const VAR3 = 3;
	//非靜態方法
	public function m1(){
		echo 'm1 working ......';
		echo PHP_EOL;
		//引入$this和self
		//類內訪問正常屬性 不用加$
		echo $this->var1;
		echo PHP_EOL;
		//類內訪問靜態屬性 要加$ 用類名也行
		echo self::$var2;
		echo ClassA::$var2;
		echo PHP_EOL;
		//類內訪問常量 就用類名 self也行
		echo ClassA::VAR3;
		echo self::VAR3;
		echo PHP_EOL;
	}
	//靜態方法
	public static function m2(){
		echo 'm2 working ......';
		echo PHP_EOL;
		//靜態方法不能訪問非靜態屬性或方法,由於沒有實例,$this沒意義
		// echo $this->var1; //Fatal error: Uncaught Error: Using $this when not in object context
		// echo PHP_EOL;
		//類內訪問靜態屬性 要加$ 用類名也行
		echo self::$var2;
		echo ClassA::$var2;
		echo PHP_EOL;
		//類內訪問常量 就用類名 self也行
		echo ClassA::VAR3;
		echo self::VAR3;
		echo PHP_EOL;
	}
}
//調用非靜態方法 
(new ClassA())->m1();
//調用靜態方法 
ClassA::m2();
//測試在類外,調用屬性
echo '----------';
echo PHP_EOL;
//非靜態屬性
echo (new ClassA())->var1;
echo PHP_EOL;
//靜態屬性
echo ClassA::$var2;
echo PHP_EOL;
//常量  
echo ClassA::VAR3;
echo PHP_EOL;
複製代碼

非靜態 訪問控制 重載和訪問父級

/*非靜態 訪問控制 重載和訪問父級*/
class ClassA{
	//屬性
	public  	$var1 = 1;
	protected  	$var2 = 2;
	private  	$var3 = 3;
	//方法
	public function m1(){
		echo 'm1 working ......';
		echo $this->var1;
		echo $this->var2;
		echo $this->var3;
		echo PHP_EOL;
	}
	protected function m2(){
		echo 'm2 working ......';
		echo $this->var1;//發現仍是4 重載就就覆蓋了 沒有方法那樣的保持層級
		echo PHP_EOL;
	}
	private function m3(){
		echo 'm3 working ......';
		echo PHP_EOL;
	}
}
$obj1 = new ClassA();
$obj1->m1();
//$obj1->m2();//Fatal error: Uncaught Error: Call to protected method ClassA::m2() 
//$obj1->m3();//Fatal error: Uncaught Error: Call to private method ClassA::m3()
echo '--------------------';
echo PHP_EOL;
class ClassB extends ClassA{
	//屬性 這裏叫重載
	public  	$var1 = 4;
	private  	$var3 = 6;
	//方法 重載m1
	public function m1(){
		echo 'm1 working ......';
		echo $this->var1;
		//echo parent::var1;//這是錯誤的 只有靜態才能這樣調用
		echo $this->var2;//沒有重載就調用父類的屬性
		echo $this->var3;
		echo PHP_EOL;
	}
	//重載m2
	public function m2(){
		echo 'class B m2 working ......';
		// echo parent::$var1; 屬性沒有這種調用,若是沒有
		echo PHP_EOL;
		parent::m2();
	}
	public function m4(){
		echo 'm4 working ......';
		// $this->m3();//Fatal error: Uncaught Error: Call to private method ClassA::m3() 
	}
}
$obj2 = new ClassB();
$obj2->m1();
$obj2->m2();
$obj2->m4();
複製代碼

靜態 訪問控制 重載和訪問父級

/*靜態 訪問控制 重載和訪問父級*/
class ClassA{
	//屬性
	public  static	$var1 = 1;
	protected  static	$var2 = 2;
	private  static	$var3 = 3;
	//方法
	public static function m1(){
		echo 'm1 working ......';
		echo self::$var1;
		echo self::$var2;
		echo self::$var3;
		echo PHP_EOL;
		self::m2();
	}
	protected static function m2(){
		echo 'm2@A working ......';
		echo PHP_EOL;
	}
	private static function m3(){
		echo 'm3 working ......';
		echo PHP_EOL;
	}
}
echo ClassA::$var1;
echo PHP_EOL;
// echo ClassA::$var2;//Fatal error: Uncaught Error: Cannot access protected property ClassA::$var2
ClassA::m1();
// ClassA::m2();//Fatal error: Uncaught Error: Call to protected method ClassA::m2() 
//$obj1->m2();//Fatal error: Uncaught Error: Call to protected method ClassA::m2() 
echo '--------------------';
echo PHP_EOL;
class ClassB extends ClassA{
	//屬性  重載
	public  static	$var1 = 4;
	//方法 重載m1
	public static function m1(){
		echo 'm1@B working ......';
		echo self::$var1;
		echo parent::$var1;
		echo self::$var2;
		// echo self::$var3;//Fatal error: Uncaught Error: Cannot access  property ClassB::$var3
		echo PHP_EOL;
		self::m2();
		parent::m2();
	}
	protected static function m2(){
		echo 'm2@B working ......';
		echo PHP_EOL;
	}
	 
}
ClassB::m1();

複製代碼

3.其餘

  • 魔術方法
    • 經常使用8
      • __construct() __destruct(),
      • __call() __callStatic(),
      • __get() __set() __isset() __unset(),
    • 不經常使用4
      • __sleep() __wakeup(),
      • __toString(),
      • __invoke(),
    • 我不會3
      • __set_state(),
      • __clone()
    • __debugInfo()
  • 相關函數
    • get_class()
    • instanceof ()
    • ::class
  • 對象操做
    • 對象序列化
    • 對象比較
    • 對象遍歷
    • 對象複製
  • 其餘
    • 類型約束
    • 應用的理解
    • 匿名類
    • static延遲綁定

魔術方法

1 __construct() __destruct() 構建和析構方法,在建立和銷燬對象時調用
2 __call() __callStatic() 調用不存在的方法時調用
3 __set(),__get(),__isset(),__unset() 攔截器系列
4 __sleep() __wakeup() 在serialize()unserialize()時調用,能夠額外加一些邏輯
5 __toString() 在echo時調用,不定義就echo會error
6 __invoke() 當以函數方式調用對象時啓動
7 __set_state() __debugInfo() 我也不知道有啥用
8 __clone() 自定義如何複製對象
/*魔術方法2*/
/*sleep wakeup invoke toString*/
class B{
	function __construct($name,$age){
		$this->name = $name;
		$this->age = $age;
	}
	function __sleep(){
		echo $this->name.'is sleep';
		echo PHP_EOL;
		return array('name','age');
	}
	function __wakeup(){
		echo $this->name.'is wakeup';
		echo PHP_EOL;
	}
	function __toString(){
		return  'i am '.$this->name;
	}
	function invoke($arg){
		echo 'what are u doing';
		echo PHP_EOL;
	}
}
//sleep
$obj = new B('hahaha','19');
$data = serialize($obj);
var_dump($data);
$test = unserialize($data);
//tostring
echo $test;
//invoke
$test('111');
/*魔術方法1*/
/*構建 析構 call get*/
class A{
	public $name = 'default';
	public $data = [];
	//構建方法
	public function __construct($name=NULL){
		if($name){
			$this->name = $name;
		}
		echo '__construct runing.....';
		echo PHP_EOL;
	}
	//析構方法
	public function __destruct(){
		echo '__destruct runing.....';
		echo PHP_EOL;
	}
	//攔截器
	public function __call($name,$arguments){
		echo 'you are try to run method'.$name.'but its not exists';
		echo PHP_EOL;
	}
	public static function __callStatic($name,$arguments){
		echo 'you are try to run static method'.$name.'but its not exists';
		echo PHP_EOL;
	}
	//獲取器設置器
	public function __set($name,$value){
		$this->data[$name] = $value;
		echo 'setter runing ';
		echo PHP_EOL;
	}
	public function __get($name){
		if(isset($this->data[$name])){
			return  $this->data[$name];
		}else{
			return 'empty';
		}
	}
	public function __isset($name){
		if(isset($this->data[$name])){
			echo 'Y';
		}else{
			echo 'N';
		}
		echo PHP_EOL;	
	}
	public function __unset($name){
		if(isset($this->data[$name])){
			unset($this->data[$name]);
		}
		echo 'done ';
		echo PHP_EOL;	
	}
}
$obj = new A('xyz');
echo $obj->name;
echo PHP_EOL;
$obj->tag = 'mmmm';
echo $obj->tag;
echo PHP_EOL;
echo $obj->bag;
echo PHP_EOL;
echo $obj->run();
echo PHP_EOL;
echo A::fly();
echo PHP_EOL;
複製代碼

static有兩種意思

  • 1.區分做用域在類仍是對象,靜態變量是類做用域
  • 2.有「最初調用類」的意思,主要2個用法,
    • new static,
    • 和延遲靜態綁定static::funct()
相關文章
相關標籤/搜索