php的static靜態方法是什麼

2022-10-31 10:00:31

php static靜態方法中的「靜態」指的是無需對類進行範例化,就可以直接呼叫這些屬性和方法;而static就是一個關鍵字,用來修飾類的屬性及方法,其使用語法如「class Foo {public static $my_static = 'hello';}」。

php入門到就業線上直播課:進入學習
Apipost = Postman + Swagger + Mock + Jmeter 超好用的API偵錯工具:

本教學操作環境:windows7系統、PHP8.1版、Dell G3電腦。

PHP static靜態詳解

PHP 類屬性和方法都需要在類範例化後才能呼叫(常數屬性除外),但是,PHP 還提供了靜態屬性和靜態方法,所謂「靜態」指的是無需對類進行範例化,就可以直接呼叫這些屬性和方法。靜態類不是不可以範例化,而是不需要範例化就可以用。

靜態成員的定義

用static關鍵字來修飾類的屬性、方法,稱這些屬性、方法為靜態屬性、靜態方法。

1、靜態屬性

語法:

static 屬性名
登入後複製

範例:

<?php
class Foo {
  public static $my_static = 'hello';  
}
?>
登入後複製

2、靜態方法

語法:

static function 方法名{
    //程式碼
}
登入後複製

範例:

<?php
class Foo {
  public static function staticValue() {
     return 'hello';
  }
}
?>
登入後複製

注:靜態屬性和方法與物件屬性和方法一樣,支援設定 privateprotectedpublic 三種可見性級別。

靜態成員的呼叫

1、在類外呼叫靜態屬性/方法

通過 類名::屬性/方法 的方式呼叫。

<?php
class Mystatic {
  public static $staticvalue = 'zhangsan';
  public static function staticMethod() {
    $a = 'hello';
    return $a;
  }
}
echo '$staticvalue: '.Mystatic::$staticvalue.PHP_EOL;
echo '$a: '.Mystatic::staticMethod().PHP_EOL;
?>
登入後複製

注:預定義常數 PHP_EOL 表示系統換行符。

結果:

$staticvalue: zhangsan
$a: hello
登入後複製
登入後複製
登入後複製

通過 物件名::屬性/方法 的方式呼叫。

<?php
class Mystatic {
  public static $staticvalue = 'zhangsan';
  public static function staticMethod() {
    $a = 'hello';
    return $a;
  }
}
$obj = new Mystatic();
echo '$staticvalue: '.$obj::$staticvalue.PHP_EOL;
echo '$a: '.$obj::staticMethod();
?>
登入後複製

結果:

$staticvalue: zhangsan
$a: hello
登入後複製
登入後複製
登入後複製

通過物件名 -> 方法呼叫、物件名 -> 屬性會失敗。

<?php
error_reporting(0);
class Mystatic {
  public static $staticvalue = 'zhangsan';
  public static function staticMethod() {
    $a = 'hello';
    return $a;
  }
}
$obj = new Mystatic();
echo '$staticvalue: '.$obj -> staticvalue.PHP_EOL;
echo '$a: '.$obj -> staticMethod();
?>
登入後複製

結果:

$staticvalue:
$a: hello
登入後複製

2、在非靜態方法中呼叫靜態屬性/方法

通過 self::屬性/方法 的方式呼叫,self 指向當前類,就像 $this 指向當前物件一樣;而在沒有範例化的情況下,$this 指標指向的是空物件,所以不能動過它參照靜態屬性和方法。

<?php
class Mystatic {
  public static $staticvalue = 'zhangsan';
  public static function staticMethod() {
    $a = 'hello';
    return $a;
  }
  public function noStatic(){
    echo '$staticvalue: '.self::$staticvalue.PHP_EOL;
    echo '$a: '.self::staticMethod();

  }
}
$obj = new Mystatic();
$obj -> noStatic();
?>
登入後複製

結果:

$staticvalue: zhangsan
$a: hello
登入後複製
登入後複製
登入後複製

3、在靜態方法中呼叫靜態屬性/方法

與在非靜態方法中呼叫靜態屬性/方法一樣。

<?php
class Mystatic {
  public static $staticvalue = 'zhangsan';
  public static function staticMethod1() {
    $a = 'hello';
    return $a;
  }
  public static function staticMethod2(){
    echo '$staticvalue: '.self::$staticvalue.PHP_EOL;
    echo '$a: '.self::staticMethod1().PHP_EOL;

  }
}
Mystatic::staticMethod2();
$obj = new Mystatic();
$obj -> staticMethod2();
?>
登入後複製

結果:

$staticvalue: zhangsan
$a: hello
$staticvalue: zhangsan
$a: hello
登入後複製

4、呼叫另一個類的靜態屬性/方法

如果在一個類中呼叫其他類的靜態屬性和方法,需要通過 完整類名:: 進行參照。

<?php
class Mystatic1 {
  public static $staticvalue1 = 'xiaomin';
}
class Mystatic2 {
  public static $staticvalue2 = 'zhangsan';
  public static function staticMethod() {
    echo '$staticvalue1: '.Mystatic1::$staticvalue1.PHP_EOL;
    echo '$staticvalue2: '.self::$staticvalue2.PHP_EOL;

  }
}
Mystatic2::staticMethod();
$obj = new Mystatic2();
$obj -> staticMethod();
?>
登入後複製

結果:

$staticvalue1: xiaomin
$staticvalue2: zhangsan
$staticvalue1: xiaomin
$staticvalue2: zhangsan
登入後複製

5、呼叫privateprotected可見性級別的靜態屬性/方法

由於privateprotected屬性的限制只在類內呼叫,想在類外呼叫,需為外部提供一個public的方法,方法存取privateprotected屬性。術語:類對外提供介面。

<?php
class Mystatic {
  public static $staticvalue1 = 'zhangsan';
  private static $staticvalue2 = 20;
  protected static $staticvalue3 = 'student';
  private static function staticMethod() {
    $a = 'hello';
    return $a;
  }
  public function port1() {
    echo '$staticvalue1: '.self::$staticvalue1.PHP_EOL;
    echo '$staticvalue2: '.self::$staticvalue2.PHP_EOL;
    echo '$staticvalue3: '.self::$staticvalue3.PHP_EOL;
    echo '$a: '.self::staticMethod().PHP_EOL;
  }
  public static function port2() {
    echo '$staticvalue1: '.self::$staticvalue1.PHP_EOL;
    echo '$staticvalue2: '.self::$staticvalue2.PHP_EOL;
    echo '$staticvalue3: '.self::$staticvalue3.PHP_EOL;
    echo '$a: '.self::staticMethod().PHP_EOL;
  }
}
$obj = new Mystatic();
$obj -> port1();
echo "\r\n";
Mystatic::port2();
?>
登入後複製

結果:

$staticvalue1: zhangsan
$staticvalue2: 20
$staticvalue3: student
$a: hello

$staticvalue1: zhangsan
$staticvalue2: 20
$staticvalue3: student
$a: hello
登入後複製

靜態屬性支援動態修改

在實際應用中會有一個類的多個物件,可能會共用一份資料。類常數和靜態屬性都可以實現。靜態屬性與類常數相似(相同),唯一的區分是類常數不可以更改,靜態屬性可以更改。存取方法是一樣的,都可以使用::存取。 靜態屬性需要加$,常數名前沒有$,所以存取類常數時根本不需要加。

1、類常數

<?php
class Myconst {
  const A = 1234;
}
$obj1 = new Myconst();
echo 'A: '.$obj1::A.PHP_EOL;
$obj1->A='aaa';
//$obj1::A='aaa';會報錯
echo "\r\n";
$obj2 = new Myconst();
echo 'A: '.$obj2::A.PHP_EOL;
?>
登入後複製

結果:

A: 1234

A: 1234
登入後複製

2、靜態屬性

<?php
class Mystatic {
  public static $A = 1234;
}
echo '$A: '.Mystatic::$A.PHP_EOL;
Mystatic::$A = 6666;
echo '$A: '.Mystatic::$A.PHP_EOL;
$obj1 = new Mystatic();
echo '$A: '.$obj1::$A.PHP_EOL;
Mystatic::$A = 5555;
$obj2 = new Mystatic();
echo '$A: '.$obj2::$A.PHP_EOL;
echo '$A: '.$obj1::$A.PHP_EOL;
?>
登入後複製

結果:

$A: 1234
$A: 6666
$A: 6666
$A: 5555
$A: 5555
登入後複製

靜態成員的繼承和重寫

和非靜態屬性/方法一樣,靜態屬性和方法也可以被子類繼承,靜態屬性和方法還可以被子類重寫。

1、靜態屬性

子類可以重寫父類別的靜態成員變數, 但父類別的靜態變數依然存在, 這兩個靜態成員變數是獨立的. 會根據呼叫的類名分別進行存取。

<?php
class Mystatic
{
    static public $a;           //定義一個靜態變數
    static function test()        //定義靜態方法來操作並輸出靜態變數
    {
        self::$a++;
        return self::$a;
    }
}
class Mystatic2 extends  Mystatic          //定義一個子類
{
    static function test()           //定義子類的靜態方法
    {
        self::$a++;                 //存取並操作父類別的靜態變數
        return self::$a;
    }
}
$obj1=new Mystatic;                              //新建父類別物件
echo '此時$a的值為: '.$obj1->test().PHP_EOL;     //通過物件呼叫靜態方法test,靜態屬性$a的值+1
$obj2=new Mystatic;                              //新建另一個父類別物件
echo '此時$a的值為: '.$obj2->test().PHP_EOL;     //新父類別物件呼叫靜態方法test,靜態屬性$a的值+1+1
$obj3=new Mystatic2;                             //新建子類物件
echo '此時$a的值為: '.$obj3->test().PHP_EOL;     //子類物件呼叫同名靜態方法test, 靜態屬性$a的值+1+1+1
echo Mystatic::$a.PHP_EOL;    //通過父類別::直接存取靜態成員$a變數
echo $obj1::$a.PHP_EOL;   //通過物件名::可以直接存取靜態成員$a變數
?>
登入後複製

結果:

此時$a的值為: 1
此時$a的值為: 2
此時$a的值為: 3
3
3
登入後複製

2、靜態方法

子類可以重寫父類別的靜態方法。

<?php
class Mystatic1 {
    public static function getclassName() {
        return __CLASS__;
    }

    public static function whoclassName() {
        echo self::getclassName().PHP_EOL;
    }
}

class Mystatic2 extends Mystatic1{
    public static function getclassName() {
        return __CLASS__;
    }
}

echo Mystatic1::getclassName().PHP_EOL;
echo Mystatic2::getclassName().PHP_EOL;
?>
登入後複製

通過 __CLASS__ 可以獲取當前類的類名,我們分別呼叫兩個類的 getClassName 方法:

結果:

Mystatic1
Mystatic2
登入後複製
登入後複製

說明子類重寫了父類別的同名靜態方法,同樣我們在子類上也可以呼叫父類別中的 whoclassName 方法:

<?php
class Mystatic1 {
    public static function getclassName() {
        return __CLASS__;
    }

    public static function whoclassName() {
        echo self::getclassName().PHP_EOL;
    }
}

class Mystatic2 extends Mystatic1{
    public static function getclassName() {
        return __CLASS__;
    }
}

echo Mystatic1::whoclassName();
echo Mystatic2::whoclassName();
?>
登入後複製

結果:

Mystatic1
Mystatic1
登入後複製

為什麼第二個列印的結果是父類別名 Mystatic1 而不是子類名 Mystatic2?這是因為, $this 指標始終指向持有它的參照物件,而self 指向的是定義時持有它的類而不是呼叫時的類,為了解決這個問題,從 PHP 5.3 開始,新增了一個叫做延遲靜態繫結的特性。

延遲靜態繫結

延遲靜態繫結(Late Static Bindings)針對的是靜態方法的呼叫,使用該特性時不再通過 self:: 參照靜態方法,而是通過 static::,如果是在定義它的類中呼叫,則指向當前類,此時和 self 功能一樣,如果是在子類或者其他類中呼叫,則指向呼叫該方法所在的類

<?php
class Mystatic1 {
    public static function getclassName() {
        return __CLASS__;
    }

    public static function whoclassName() {
        echo static::getclassName().PHP_EOL;
    }
}

class Mystatic2 extends Mystatic1{
    //self改為static
    public static function getclassName() {
        return __CLASS__;
    }
}
echo Mystatic1::whoclassName();
echo Mystatic2::whoclassName();
?>
登入後複製

結果:

Mystatic1
Mystatic2
登入後複製
登入後複製

表明後期靜態繫結生效,即 static 指向的是呼叫它的方法所在的類,而不是定義時,所以稱之為延遲靜態繫結。

此外,還可以通過 static::class 來指向當前呼叫類的類名,例如我們可以通過它來替代 __CLASS__,這樣上述子類就沒有必要重寫 getClassName 方法了:

<?php
class Mystatic1 {
    public static function getclassName() {
        return static::class;
    }

    public static function whoclassName() {
        echo static::getclassName().PHP_EOL;
    }
}

class Mystatic2 extends Mystatic1{}

echo Mystatic1::getclassName().PHP_EOL;
echo Mystatic2::getclassName().PHP_EOL;
echo Mystatic1::whoclassName();
echo Mystatic2::whoclassName();
?>
登入後複製

結果:

Mystatic1
Mystatic2
Mystatic1
Mystatic2
登入後複製

同理,self::class 則始終指向的是定義它的類。

靜態與非靜態的區別

  • 靜態屬性和方法可以直接通過類參照,所以又被稱作類屬性和類方法。非靜態屬性和非靜態方法需要範例化後通過物件參照,因此被稱作物件屬性和物件方法。

  • 靜態屬性儲存在類空間,非靜態屬性儲存在物件空間。非靜態方法可以存取類中的任何成員(包括靜態),靜態方法只能存取類中的靜態成員。

  • 靜態方法可以直接呼叫,類名呼叫和物件呼叫(類名或self::呼叫),但是非靜態方法只能通過物件呼叫(物件名或$this->呼叫)。

  • 一個類的所有範例物件,共用類中的靜態屬性。如果修改了這個類靜態屬性,那麼這個類的所有物件都能存取到這個新值。

  • 靜態方法和屬性的生命週期跟相應的類一樣長,靜態方法和靜態屬性會隨著類的定義而被分配和裝載入記憶體中。一直到執行緒結束,靜態屬性和方法才會被銷燬。 非靜態方法和屬性的生命週期和類的範例化物件一樣長,只有當類範例化了一個物件,非靜態方法和屬性才會被建立,而當這個物件被銷燬時,非靜態方法也馬上被銷燬。靜態方法和靜態變數建立後始終使用同一塊記憶體,而使用範例的方式會建立多個記憶體。但靜態方法效率上要比範例化高,靜態方法的缺點是不自動進行銷燬,而範例化的則可以做銷燬。

應用場景:

  1. 靜態方法最適合工具類中方法的定義;比如檔案操作,日期處理方法等.

  2. 靜態變數適合全域性變數的定義.

推薦學習:《》

以上就是php的static靜態方法是什麼的詳細內容,更多請關注TW511.COM其它相關文章!