2015-06-20 20 views
9

Perché in PHP 7 non è possibile dichiarare un'interfaccia con un tipo di ritorno static?tipo di ritorno statico in PHP 7 interfacce

Diciamo Ho le seguenti classi:

interface BigNumber { 
    /** 
    * @param BigNumber $that 
    * 
    * @return static 
    */ 
    public function plus(BigNumber $that); 
} 

class BigInteger implements BigNumber { ... } 
class BigDecimal implements BigNumber { ... } 

voglio rispettare il tipo di ritorno del metodo plus()-static, cioè:

  • BigInteger::plus() deve restituire un BigInteger
  • BigDecimal::plus() deve restituire un BigDecimal

posso dichiarare l'interfaccia nel modo seguente:

public function plus(BigNumber $that) : BigNumber; 

Ma ciò non rispettare la precedenza. Quello che vorrei fare è:

public function plus(BigNumber $that) : static; 

Ma PHP 7, ad oggi, non è soddisfatto:

PHP Parse error: syntax error, unexpected 'static' (T_STATIC)

C'è una ragione specifica per questo, o si tratta di un bug che dovrebbe essere segnalato?

+2

Invarianza di tipo, ecco perché. I metodi di implementazione/sovrascrittura devono corrispondere esattamente al tipo in PHP; 'static' no - ovviamente, perché si riferisce al contesto corrente e quindi non può essere invarianza. –

risposta

5

Non è un bug, non ha senso dal punto di vista del design orientato agli oggetti.

Se il vostro BigInteger e BigDecimal implementano entrambi BigNumber, vi preoccupate del contratto che soddisfano. In questo caso, è l'interfaccia di BigNumber.

Quindi il tipo di reso che dovresti usare nell'interfaccia è BigNumber dato che chiunque codifica su quell'interfaccia non sa nient'altro che i membri di quell'interfaccia. Se hai bisogno di sapere quale viene restituito, l'interfaccia è forse troppo ampia in primo luogo.

Nota: i linguaggi di programmazione con generici possono ottenere questo effetto specificando il tipo restituito come tipo generico, ma PHP non ha generici e probabilmente non lo sarà nel prossimo futuro.

+2

La mia idea era di essere flessibile sull'input (puoi confrontare un 'BigInteger' con un' BigDecimal' per esempio), ma rigoroso sull'output (qualunque metodo chiamato su una classe dovrebbe restituire un'istanza della stessa classe). Forse non ha senso, ma almeno PHPdoc consente questo tipo di utilizzo ('@return static')! – Benjamin

+0

Bene PHPDoc in realtà non sa nulla di 'static' http://www.phpdoc.org/docs/latest/references/phpdoc/types.html, il più vicino è' self' che in questo caso è identico all'interfaccia ritorno suggerimento tipo. – vvondra

+2

Stranamente, questo: http://www.phpdoc.org/docs/latest/guides/types.html effettivamente documenta 'static':" un oggetto della classe in cui è stato utilizzato questo valore, se ereditato rappresenterà il bambino class. (vedi il binding statico avanzato nel manuale di PHP). " – Benjamin