大概1年前我總結過,可是那時候太菜,如今我又來總結了。 (本文是總結,不是入門,剛學oop的不適合看,基礎寫的比較省略。)php
其實oop編程發展到如今,知識點不少,並且很雜,好比static就很亂,很容易混淆,我本身這麼分類:編程
類和對象是模擬現實中,一羣類似的物體,以及他們的抽象模板的關係,在編程中便於將方法(功能)和屬性(數據)組織到一塊兒,作到封裝,解耦,提升代碼的健壯性和複用性。 是一個很是重要的概念發明。bash
類和對象的基本概念一言難盡,總結:app
屬性和方法,都有三種可見性,分別用三個單詞去修飾函數
在類的外部可訪問 | 子類可訪問 | |
---|---|---|
public | Y | Y |
protected | N | Y |
private | N | N |
類由屬性和方法組成,屬性和方法能夠調用,一個類實例化成多個對象後,每一個對象都有本身的屬性和方法,並且調用一樣的方法後結果不必定同樣,這叫多態。工具
然而屬性和方法不必定要實例化後才能調用,定義爲static的屬性和方法就是直接能夠調用,無需實例化。oop
我這麼理解,類是一個特殊的做用域,就當成一個特殊的對象,他持有靜態屬性和靜態方法,對象也能夠調用靜態方法,可是類不能調用非靜態方法。測試
對象改變靜態屬性的值後,當對象銷燬了,靜態屬性的值還在,由於他屬於類。ui
使用類前必須定義類,當前文件沒有這個類,就要include,當應用變大,就會很難搞。 就要用到自動加載。this
自動加載就是依靠spl_autoload_register()
實現,參數是一個函數,當找不到使用的類的時候,就會將類名做爲參數傳入註冊的函數。
<?php
spl_autoload_register(function($class_name){
require_once 'www/app/lib/'.$calss_name.'.php';
})
複製代碼
構造函數是最重要的一個魔術方法,因此提早單說。
發明類和對象的關係已經很厲害了,可是還不夠,爲了處理更加複雜的關係,出現了對象層級。
一個對象能夠繼承另外一個對象,這樣能夠更好得組織代碼和複用代碼。而後還有抽象類,接口和trait都是oop中組織和複用代碼的工具。
一言難盡,直接說重點
是否多繼承 | 代碼是有功能性的仍是規範性的 | |
---|---|---|
類 | N | 功能 |
抽象類 | N | 規範(主要)和功能 |
接口 | Y | 規範 |
trait | Y | 功能(主要)和規範 |
注意
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();
複製代碼
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;
複製代碼