1. 程式人生 > >面向物件(三)

面向物件(三)

前言:續上寒冬的熱火,學習不能停,不能停

(一)final關鍵字

  分類:

  1.使用final關鍵字定義的類,我們稱其為 final類或最終類

  2.使用final關鍵字定義的類中的方法,我們稱其為 final方法或最終方法

  定義:

//使用final關鍵字申明類
final  class  類名{
    類成員
}
//特點
不能被別的類繼承了
//使用final關鍵字申明方法
final  public/protected [static] function  方法名(){
    方法體
}
//特點
不能被重寫

 

(二) 抽象類

  表現:

//使用abstract申明一個抽象類
abstract  class  類名{
    抽象類成員
}

  組成:

  1.普通類的所有的成員

  2.抽象方法

<?php

#定義一個抽象類
abstract class A{

    #普通類的所有成員
    public $var1;
    public static $var2;
    const PATH='./source/';
    public function f1(){ 
        echo 'f1'; 
    }
    public static function f2(){ 
        
echo 'static_f2'; } #抽象方法 比普通方法多了個abstract關鍵字,少了方法體 abstract public function f3($v1, $v2); }

  特點:

  1.抽象類只能被繼承,不能被直接例項化為物件,但是抽象類中的靜態成員和類常量都能夠正常使用;

<?php

#定義一個抽象類
abstract class A{

    #普通類的所有成員
    public $var1='var1';
    public static $var2='var2';
    const PATH='./source/';
    
public function f1(){ echo 'f1'; } public static function f2(){ echo 'static_f2'; } } var_dump( A::$var2 ); echo '<br/>'; //呼叫抽象類中的靜態成員屬性 var_dump( A::PATH ); echo '<br/>'; //呼叫抽象類中的類常量 A::f2();//呼叫抽象類中的靜態方法 $a1 = new A;//抽象類不能被用來例項化為物件

  2.抽象類如果被普通類所繼承,那麼抽象類中的抽象方法必須全部被實現;

<?php

#定義一個抽象類
abstract class A{

    #普通類的所有成員
    public $var1='var1';

    #抽象方法
    abstract public function f1($v1);
    abstract public function f2($v1, $v2, $v3);
    abstract protected function f3();
}

class B extends A{

    //實現抽象類中的抽象方法   去掉abstract關鍵字,補上方法的方法體
    public function f1($v1){
    
    }

    public function f2($v1, $v2, $v3){ 
        
    }

    protected function f3(){ 
        
    }
}

  3.抽象類還可以被抽象類所繼承,如果被抽象類所繼承,那麼被繼承的那個抽象類中其抽象方法可以不被實現;

<?php

#定義一個抽象類
abstract class A{

    #普通類的所有成員
    public $var1='var1';

    #抽象方法
    abstract public function f1($v1);
    abstract public function f2($v1, $v2, $v3);
    abstract protected function f3();
}

abstract class B extends A{

}

 

(三) PHP中的介面

  區別:PHP中的介面指的不是我們平時聽到的支付介面,物流介面之類的api,而是特指PHP中的一種語法;

  表現:

interface  介面名{
    介面成員
}

  成員:

  1.介面常量

  2.介面抽象方法 

  定義方式:

<?php

#定義一個PHP中的介面
interface inter1{
    #介面成員
    //介面常量
    const PATH='./source';

    //介面抽象方法   比抽象類中的抽象方法少了abstract關鍵字
    public function f1($v1, $v2);
}

  特點:

  1.介面需要使用implements關鍵字來實現;

<?php

#定義一個PHP中的介面
interface inter1{

    #介面成員
    //介面常量
    const PATH='./source';
}

//介面需要使用關鍵字implements來實現
class A implements inter1{

}

  2.介面可以被多實現

<?php

#定義一個PHP中的介面
interface inter1{

    #介面成員
    //介面常量
    const PATH='./source';
}

interface inter2{
    
}

//介面可以一次性被實現多個
class A implements inter1, inter2{

}

  3.介面如果被普通類所實現,那麼,介面中的所有介面抽象方法都要被全部實現;

<?php

#定義一個PHP中的介面
interface inter1{

    #介面成員
    //介面常量
    const PATH='./source';

    //介面抽象方法   比抽象類中的抽象方法少了abstract關鍵字
    public function f1($v1, $v2);
    public function f2($v1, $v2);
}

class A implements inter1{

    //只要補上方法體的大括號就叫做實現了介面的抽象方法
    public function f1($v1, $v2){ 
        
    }

    public function f2($v1, $v2){ 
        
    }
}

  4.介面還可以被抽象類所實現,如果被抽象類實現,那麼介面中的介面抽象方法可以不被實現

<?php

#定義一個PHP中的介面
interface inter1{

    #介面成員
    //介面常量
    const PATH='./source';

    //介面抽象方法   比抽象類中的抽象方法少了abstract關鍵字
    public function f1($v1, $v2);
    public function f2($v1, $v2);
}

abstract class A implements inter1{

}

  5.介面中的介面抽象方法只能是public型別;

<?php

#定義一個PHP中的介面
interface inter1{

    #介面成員
    //介面常量
    const PATH='./source';

    //介面抽象方法   比抽象類中的抽象方法少了abstract關鍵字
    //protected function f1($v1, $v2);
    //private function f1($v1, $v2);
    public function f1($v1, $v2);//介面中的介面抽象方法只能是public型別,其他型別將會直接報錯
}

 

(四) 靜態延時繫結

  引言:靜態延時繫結是PHP5.3之後才出現的特性。

  靜態延時繫結需要用到的關鍵字是:static

  static關鍵字的意思:表示哪個類呼叫,就代表那個類。

<?php

class StaticDemo{

    public static $var1='var1';

    public static function f1(){ 
        //訪問子類中的$var2屬性
        var_dump( Demo::$var2 ); echo '<br/>';
        var_dump( static::$var2 ); echo '<hr/>';
    }
}

class Demo extends StaticDemo{
    
    public static $var2='var2';

    public function f2(){ 
        //呼叫父類中的$var1屬性
        var_dump( parent::$var1 ); echo '<br/>';
        var_dump( StaticDemo::$var1 ); echo '<br/>';
        var_dump( self::$var1 ); echo '<br/>';
        var_dump( Demo::$var1 ); echo '<br/>';
        var_dump( static::$var1 ); echo '<hr/>';echo '<hr/>';

        //呼叫本類中的$var2屬性
        var_dump( self::$var2 ); echo '<br/>';
        var_dump( Demo::$var2 ); echo '<br/>';
        var_dump( static::$var2 );
    }
}

 

(五) PHP的過載

  概念:PHP中的過載,指的是當訪問一個不可訪問(不存在的成員或存在卻不能訪問的成員)的成員時,如何來進行處理,這個處理過程就是PHP中的過載。

  分類:

  1.預設的過載 當訪問一個不可訪問的成員時,PHP預設的處理過程

<?php

class OverloadDemo{

    protected $var1='var1';

    protected function f1($v1){ //protected型別  的  非靜態方法
        echo $v1; 
    }

    private static function f2($v1){ //private型別  的  靜態方法
        echo $v1; 
    }
}

$obj = new OverloadDemo;
var_dump( $obj ); echo '<br/>';
$obj->name = 'zhangsan';//新增一個屬性,屬於訪問到一個不可訪問的成員中的訪問到了一個不存在的成員,PHP預設幫我們把這個屬性新增進物件裡了
var_dump( $obj ); echo '<hr/>';

//var_dump( $obj->var1 ); //當我們訪問到一個不可訪問的成員屬性時(屬於訪問到一個存在但是不能訪問的成員的情況),PHP預設直接報錯

//unset($obj->var1);//當我們刪除一個不可訪問的成員時(屬於刪除到一個存在但是不能訪問的成員的情況),PHP預設直接報錯

var_dump( isset($obj->var1) ); echo '<hr/>';//當判斷一個不可訪問的成員是否存在時(屬於存在但是不能訪問的情況),PHP預設返回false

//$obj->f1(100);//當訪問到一個不可訪問的非靜態方法時(屬於存在但是不能訪問的情況),PHP預設直接報錯

OverloadDemo::f2();//當訪問到一個不可訪問的靜態方法時(屬於存在但是不能訪問的情況),PHP預設直接報錯

 

  2.自定義過載 當訪問一個不可訪問的成員時,開發者自定義的處理過程

  分為兩類:(非靜態)屬性的過載和方法的過載

  屬性的過載涉及的魔術方法:

  __get(屬性名) 當獲取一個不可訪問的(非靜態)成員屬性值時,進行自定義的處理

<?php

class __getDemo{

    protected $name='郭嘉';

    //定義__get魔術方法   $v表示之後獲取的不可訪問的成員屬性的屬性名
    public function __get($v){ 
        
        if( $v=='name' ){
            return $this->name;
        }elseif( $v=='var1' ){
            return '就不給你看';
        }
    }
}

$obj = new __getDemo;
var_dump( $obj ); echo '<hr/>';

//           $obj->name = $obj->__get('name');
var_dump( $obj->name ); echo '<br/>';
var_dump( $obj->var1 ); 

 

  __set(屬性名, 屬性值) 當設定一個不可訪問的(非靜態)成員屬性值時,進行自定義的處理

<?php

class __setDemo{

    protected $name='王翦';
    private $age=18;

    //__set魔術方法
    public function __set($v1, $v2){ 
        
        if( $v1=='name' ){
            $this->name = $v2;
        }elseif( $v1=='age' ){
            $this->age = 100;
        }else{
            echo '不允許新增額外的屬性哦!'; 
        }
    }
}

$obj = new __setDemo;
var_dump( $obj ); echo '<br/>';
$obj->name = '王賁';
var_dump( $obj ); echo '<br/>';
$obj->age = 3.14;
var_dump( $obj ); echo '<br/>';
$obj->height = 3.16;
echo '<br/>';
var_dump( $obj ); 

 

  __unset(屬性名) 當刪除一個不可訪問的(非靜態)成員屬性時,進行自定義的處理

class __unsetDemo{

    protected $name='夢奇';
    private $age=19;

    //__unset魔術方法   需要指定一個必填引數,是不可訪問的成員屬性屬性名
    public function __unset($v1){ 
        
        if( $v1=='age' ){
            unset($this->age);
            return true;  //不要指定返回值,即使指定了返回值也無效
        }else{
            echo '再刪!給你小拳拳哦!'; 
        }
    }
}

$obj = new __unsetDemo;
var_dump( $obj ); echo '<br/>';
unset($obj->name); echo '<br/>';
var_dump( $obj ); echo '<br/>';
unset($obj->age); echo '<br/>';
var_dump( $obj ); 

 

  __isset(屬性名) 當判斷一個不可訪問的(非靜態)成員屬性是否存在時,進行自定義的處理

<?php

class __issetDemo{

    protected $name='二師兄';
    private $age=19;

    //__isset魔術方法  需要指定一個必填參,是不可訪問的成員屬性的屬性名
    public function __isset($v1){ 
        
        if( $v1=='name' ){
            return true;
        }else{
            return false;
        }
    }
}

$obj = new __issetDemo;
var_dump( isset($obj->name) ); echo '<br/>';
var_dump( isset($obj->age) ); echo '<br/>';
var_dump( isset($obj->var1) ); 

  __call(方法名, 傳遞給方法的引數) 當訪問一個不可訪問的(非靜態)成員方法時,進行自定義處理

<?php

class __callDemo{

    private function f1($v1, $v2){ 
        echo $v1; 
    }

    //__call魔術方法  需要2個必填參,第一個引數是不可訪問的方法的方法名;第二個引數是傳遞給該方法的所有引數所形成的陣列
    public function __call($v1, $v2){ 
        
        if( $v1=='f1' ){
            $this->f1($v2[0], $v2[1]);
        }else{
            echo '再來就給你小拳拳喲~'; 
        }
    }
}

$obj = new __callDemo;
$obj->f1('hello', 10);// 相當於PHP自動這樣做:$obj->__call('hello', 10);

  __callstatic(方法名, 傳遞給方法的引數) 當訪問一個不可訪問的(靜態)成員方法時,進行自定義處理

<?php

class __callStaticDemo{

    private static function f1($v1, $v2){ 
        echo $v1; 
    }

    //__callstatic魔術方法  需要2個必填參,第一個引數是不可訪問的方法的方法名;第二個引數是傳遞給該方法的所有引數所形成的陣列
    public static function __callstatic($v1, $v2){ 
        
        if( $v1=='f1' ){
            self::f1($v2[0], $v2[1]);
        }else{
            echo '再來就給你小拳拳喲~'; 
        }
    }
}

__callStaticDemo::f1('hi~', 10);