Nuovo sé vs. nuovo statico


513

Sto convertendo una libreria PHP 5.3 per lavorare su PHP 5.2. La cosa principale che si frappone sulla mia strada è l'uso dell'associazione statica tardiva come return new static($options);, se la converto in return new self($options)otterrò gli stessi risultati?

Qual è la differenza tra new selfe new static?

Risposte:


890

otterrò gli stessi risultati?

Non proprio. Tuttavia, non conosco una soluzione alternativa per PHP 5.2.

Qual è la differenza tra new selfe new static?

self si riferisce alla stessa classe in cui il new parola chiave è effettivamente scritta.

static, nelle ultime associazioni statiche di PHP 5.3, si riferisce a qualsiasi classe nella gerarchia su cui hai chiamato il metodo.

Nel seguente esempio, Beredita entrambi i metodi da A. L' selfinvocazione è vincolata Aperché è definita Anell'implementazione del primo metodo, mentre staticè legata alla classe chiamata (vedi anche get_called_class()).

class A {
    public static function get_self() {
        return new self();
    }

    public static function get_static() {
        return new static();
    }
}

class B extends A {}

echo get_class(B::get_self());  // A
echo get_class(B::get_static()); // B
echo get_class(A::get_self()); // A
echo get_class(A::get_static()); // A

ha senso. Penso che la scommessa migliore sia passare il nome della classe alla funzione che sta utilizzando l'associazione statica tardiva e quindi restituire il nuovo $ className ($ opzioni);
Mike

12
Non devi "passare" il nome della classe, puoi sempre farlo get_called_class(), che è effettivamente lo stesso di __CLASS__, ma compatibile con LSB.
Shadowhand

7
get_called_class non esiste in <PHP5.3. Pertanto, se si desidera ottenere il nome della classe dell'oggetto istanziato in PHP5.2 Questa funzione non è utile quando si tenta di convertire una libreria da PHP 5.3 a PHP 5.2
txwikinger

2
La funzione chiamata self :: theFunction () si comporta come "Eseguirò nel contesto della classe a cui appartengo fisicamente." e la funzione chiamata static :: theFunction () si comporta come "Eseguirò nel contesto della classe che è stata effettivamente chiamata dal mondo esterno". (Supponendo lo scenario di ereditarietà). Grazie
Shubhranshu

2
Nella mia testa, prendo tutto ciò che è intuitivo e lo faccio opposto. Penseresti in base alla denominazione, selftorneresti da solo, e staticrestituiresti qualcosa che non può essere ignorato ... Ma ecco ed ecco che è il contrario. Non smetto mai di essere colpito dal nome, dalle convenzioni e dallo stile generale di PHP. -_-
ahnbizcad

23

Se il metodo di questo codice non è statico, è possibile ottenere una soluzione alternativa in 5.2 utilizzando get_class($this).

class A {
    public function create1() {
        $class = get_class($this);
        return new $class();
    }
    public function create2() {
        return new static();
    }
}

class B extends A {

}

$b = new B();
var_dump(get_class($b->create1()), get_class($b->create2()));

I risultati:

string(1) "B"
string(1) "B"

17
Se il metodo non è statico, i binding statici in ritardo diventano totalmente irrilevanti.
BoltClock

1
Ad esempio, è possibile utilizzarlo nel metodo "copia", in cui l'oggetto viene copiato senza utilizzare clone, ma semplicemente ricreando e impostando le proprietà. $copy = new static(); $copy->set($this->get()); return $copy;
Marius Balčytis,

9
@BoltClock Sicuramente no? Se stai chiamando un metodo statico ignorato all'interno di un metodo di istanza di una sottoclasse, la tua scelta self::o static::influenzerà se viene utilizzata la versione della classe base o della sottoclasse di quel metodo statico. In assenza di qualche motivo per pensare che una situazione del genere si verifichi intrinsecamente cattiva pratica (e non vedo alcun motivo per cui questo dovrebbe essere così), la scelta tra self::ed static::è altrettanto rilevante nei metodi non statici come in metodi statici. Ho frainteso il tuo commento o uno di noi è semplicemente sbagliato?
Mark Amery,

4
@Mark Amery: Hmm, non ci ho pensato. Hai assolutamente ragione. Avevo supposto che nessun metodo statico sarebbe stato chiamato nel metodo dell'istanza in questione, ma sulla base del tuo esempio, posso vedere come sarebbe un'ipotesi molto ingenua.
BoltClock


7

Oltre alle risposte degli altri:

static :: verrà calcolato utilizzando le informazioni di runtime.

Ciò significa che non è possibile utilizzare static::in una proprietà di classe perché i valori delle proprietà:

Deve essere in grado di essere valutato in fase di compilazione e non deve dipendere dalle informazioni di runtime.

class Foo {
    public $name = static::class;

}

$Foo = new Foo;
echo $Foo->name; // Fatal error

utilizzando self::

class Foo {
    public $name = self::class;

}
$Foo = new Foo;
echo $Foo->name; // Foo

Si noti che il commento di errore irreversibile nel codice che ho creato non indica dove si è verificato l'errore, l'errore si è verificato in precedenza prima che l'oggetto fosse istanziato come @Grapestain menzionato nei commenti


4
Si noti che l'errore viene generato sulla riga 2 public $name = static::class;, non sulla riga 7, come suggerito dall'esempio. L'errore dice: "static :: class non può essere usato per la risoluzione del nome della classe in fase di compilazione" che indica che il problema non è dove si tenta di accedere al campo $ name, ma molto prima, durante la compilazione della classe PHP. La linea 7 (o 6) non sarà raggiunta nel primo esempio.
sbnc.eu,

@Grapestain Il commento che ho fatto nell'esempio è stato quello di mostrare il risultato finale e non indicare dove si è effettivamente verificato l'errore. Ma comunque grazie per averlo sottolineato.
Pioggia il

Giusto, non intendevo criticare, ho solo chiarito cosa mi ha confuso prima nella speranza che potesse aiutare gli altri. Esempio utile comunque!
sbnc.eu,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.