2009-02-05 2 views
5

C'era una domanda interessante in una prova pratica a cui non ho capito la risposta. Qual è l'output del seguente codice:Chiamare il metodo statico dalla Classe B (che estende la Classe A) della Classe A

<?php 
class Foo { 
    public $name = 'Andrew'; 

    public function getName() { 
     echo $this->name; 
    } 
} 

class Bar extends Foo { 
    public $name = 'John'; 

    public function getName() { 
     Foo::getName(); 
    } 
} 

$a = new Bar; 
$a->getName(); 
?> 

Inizialmente, ho pensato che questo era produrre un errore perché i metodi statici non possono fare riferimento a $ this (almeno in PHP5). L'ho testato io stesso e in realtà esce su John.

Ho aggiunto Foo :: getName(); alla fine della sceneggiatura e ho ricevuto l'errore che mi aspettavo. Quindi, cosa cambia quando chiami un metodo statico all'interno di una classe che estende la classe da cui stai chiamando?

Qualcuno dispiacerebbe spiegare dettagliatamente cosa sta succedendo qui?

risposta

2

$ this all'oggetto nel cui contesto è stato chiamato il metodo. Quindi: $ questo è $ a-> getName() è $ a. $ questo in $ fooInstance-> getName() sarebbe $ fooInstance. Nel caso in cui $ sia impostato (in un oggetto $ a's method call) e chiamiamo un metodo statico, $ rimane assegnato a $ a.

Sembra che un sacco di confusione potrebbe derivare dall'utilizzo di questa funzione. :)

4

Se si chiama il metodo statico associato all'altro oggetto, il metodo viene eseguito nel contesto dell'oggetto corrente. Che consente l'accesso a $ questo-oggetto.

modo migliore per chiamare la superclasse metodo dall'interno della sottoclasse sarebbe:

parent::getName(); 
+0

C'è un super :: simbolo in PHP? L'unico a cui riesco a pensare è genitore :: per le classi statiche. –

+0

super non sembra funzionare, padre lo fa. – notruthless

+0

hai ragione, mi sono confuso – Ulf

1

Quando si chiama $a->getName() si fa riferimento a un oggetto specifico, $a, che è di classe Bar e quindi restituisce "Giovanni".

Foo::getName() non è valido al di fuori della funzione perché non esiste un oggetto specifico.

Io non sono sicuro che funziona in PHP, ma se si lanci l'oggetto alla superclasse come in (Foo)$a->getName() allora si otterrebbe "Andrew" come risultato. Continueresti a parlare dell'oggetto specifico ($a) ma in questo caso di tipo Foo. (Nota che non sarebbe in genere vuole fare questo)

7

Foo :: getName() sta usando uno stile PHP4 precedente di scope resolution operator per consentire un metodo sovrascritto da chiamare.

In PHP5 usereste parent :: getName() invece

E 'utile se si desidera estendere, invece di ignorare completamente il comportamento della classe base, ad esempio, questo potrebbe rendere più chiaro

class Bar extends Foo { 
    public $name = 'John'; 

    public function getName() { 
     echo "My name is "; 
     parent::getName(); 
    } 
} 
1

A volte i programmatori sono meglio a spiegare le cose nel codice che in inglese!

La prima cosa da fare qui è il concetto di sovraccarico. Quando istanziate Bar, il metodo getName() sovraccarica il metodo con lo stesso nome in Foo.

Il sovraccarico è una parte potente e importante dell'OOD.

Tuttavia, è spesso utile poter chiamare la versione di un metodo esistente nella classe Parent (Foo).

Ecco un esempio:

class Dog 
{ 
    public function getTag() 
    { 
     return "I'm a dog."; 
    } 
} 

class Skip extends dog 
{ 
    public function getTag() 
    { 
     return Dog::getTag() . " My name is Skip."; 
     // I'm using Dog:: because it matches your example. However, you should use parent:: instead. 
    } 
} 

$o = new Skip(); 
echo $o->getTag(); // Echo's: "I'm a dog. My name is Skip." 

Chiaramente questo è un esempio molto campanilistica ma illustra un punto.

La classe base è l'implementazione più generale di un tipo. In questo caso, è "Cane". Vuoi mettere le informazioni in questa classe base che è comune a tutte le istanze di quel Tipo. Ciò impedisce la duplicazione in ciascuna delle classi derivate (come "Salta").

Lo script sta sfruttando questa funzione, forse inavvertitamente.