Sena statiska bindningar

Från Wiki.linux.se
Hoppa till navigering Hoppa till sök

Sen statisk bindning

PHP implementerar en funktion som kallas sen statisk bindning (late static bindings) som kan användas för att referera till den anropade klassen i en kontext av statisk arv.

Mer specifikt fungerar sen statisk bindning genom att lagra namnet på klassen i det senaste "icke-vidarebefordrade anropet". I fallet med statiska metodanrop är detta den klass som uttryckligen nämns (vanligtvis den som står till vänster om ::-operatorn); i fallet med icke-statiska metodanrop är det objektets klass. Ett "vidarebefordrat anrop" är ett statiskt anrop som introduceras av self::, parent::, static::, eller, om man går uppåt i klasshierarkin, forward_static_call(). Funktionen get_called_class() kan användas för att hämta en sträng med namnet på den anropade klassen, och static:: introducerar dess räckvidd.

Denna funktion namngavs "sen statisk bindning" med ett internt perspektiv i åtanke. "Sen bindning" kommer från det faktum att static:: inte kommer att lösas med hjälp av klassen där metoden definierades, utan istället beräknas med runtime-information. Den kallades också en "statisk bindning" eftersom den kan användas för (men inte är begränsad till) statiska metodanrop.

Begränsningar med self::

Statiska referenser till den aktuella klassen, som self:: eller __CLASS__, löses med hjälp av den klass som funktionen tillhör, alltså där den definierades:

Exempel #1 Användning av self::

<?php
class A {
    public static function who() {
        echo __CLASS__;
    }
    public static function test() {
        self::who();
    }
}

class B extends A {
    public static function who() {
        echo __CLASS__;
    }
}

B::test();
?>

Exemplet ovan kommer att ge följande utdata:

A

Användning av sen statisk bindning

Sen statisk bindning försöker lösa denna begränsning genom att introducera ett nyckelord som refererar till klassen som ursprungligen anropades vid runtime. Det beslutades att inte introducera ett nytt nyckelord utan istället använda static som redan var reserverat.

Exempel #2 Enkel användning av static::

<?php
class A {
    public static function who() {
        echo __CLASS__;
    }
    public static function test() {
        static::who(); // Här kommer sen statisk bindning in
    }
}

class B extends A {
    public static function who() {
        echo __CLASS__;
    }
}

B::test();
?>

Exemplet ovan kommer att ge följande utdata:

B

Notera:

I icke-statiska sammanhang kommer den anropade klassen att vara objektinstansens klass. Eftersom $this-> kommer att försöka anropa privata metoder från samma räckvidd kan användning av static:: ge olika resultat. En annan skillnad är att static:: endast kan referera till statiska egenskaper.

Exempel #3 Användning av static:: i ett icke-statiskt sammanhang

<?php
class A {
    private function foo() {
        echo "framgång!\n";
    }
    public function test() {
        $this->foo();
        static::foo();
    }
}

class B extends A {
   /* foo() kommer att kopieras till B, så dess räckvidd kommer fortfarande att vara A och
    * anropet kommer att lyckas */
}

class C extends A {
    private function foo() {
        /* den ursprungliga metoden ersätts; räckvidden för den nya är C */
    }
}

$b = new B();
$b->test();
$c = new C();
$c->test();   // misslyckas
?>

Exemplet ovan kommer att ge följande utdata:

framgång!
framgång!
framgång!

Fatal error: Call to private method C::foo() from context 'A' in /tmp/test.php on line 9

Notera:

Sen statisk bindningens upplösning kommer att stanna vid ett fullständigt löst statiskt anrop utan återfall. Å andra sidan kommer statiska anrop med nyckelord som parent:: eller self:: att vidarebefordra anropsinformationen.

Exempel #4 Vidarebefordrade och icke-vidarebefordrade anrop

<?php
class A {
    public static function foo() {
        static::who();
    }

    public static function who() {
        echo __CLASS__."\n";
    }
}

class B extends A {
    public static function test() {
        A::foo();
        parent::foo();
        self::foo();
    }

    public static function who() {
        echo __CLASS__."\n";
    }
}
class C extends B {
    public static function who() {
        echo __CLASS__."\n";
    }
}

C::test();
?>

Exemplet ovan kommer att ge följande utdata:

A
C
C

Sidslut

Orginalhemsidan på Engelska : https://www.php.net/manual/en/language.oop5.late-static-bindings.php
PHP
Språkreferens
Språkreferens#Klasser_och_Objekt


Det här är en maskinöversättning av PHP-manualen till svenska. Om du hittar fel är vi tacksamma om du rapporterar dem via formuläret som finns på https://www.linux.se/kontaka-linux-se/