2013-01-20 19 views
8

È una buona idea creare oggetti che non possono essere modificati in PHP?Oggetti immutabili in PHP?

Ad esempio un oggetto data con metodi setter, ma restituisce sempre una nuova istanza dell'oggetto (con la data di modifica).

Questi oggetti potrebbero confondere gli altri utenti che usano la classe, perché in PHP ci si aspetta che l'oggetto cambi di solito?

Esempio

$obj = new Object(2); 

$x = $obj->add(5); // 7 
$y = $obj->add(2); // 4 
+0

aggiunto Vedete alcun beneficio nell'avere classi che fanno questo? Probabilmente ritengo che un approccio migliore sarebbe semplicemente quello di negare * l'instabilità * (sì l'ho inventata) su proprietà che non si desidera modificare, costringendole a creare una nuova istanza, se necessario. EDIT: Sì, cosa ha detto ThiefMaster :) –

+0

http: // StackOverflow.it/questions/7317037/php-immutable-public-member-fields questo esempio può aiutare a comprendere –

risposta

5

Un oggetto immutabile non può essere modificato dopo la sua creazione iniziale, quindi i metodi di settaggio non hanno senso poiché vanno contro quel principio di base.

È possibile implementare alcuni workaround per simulare l'immutabilità in PHP manipolando la visibilità dei membri della classe e sovrascrivendo il metodo magic __set() ma non è immutabile poiché l'immutabilità non è una funzionalità del linguaggio. Credo che qualcuno abbia scritto un'estensione per fornire un valore immutabile in PHP, quindi potresti farlo su Google.

+2

PHP RFC: classi e proprietà immutabili https://wiki.php.net/rfc/immutability –

+0

Per quanto riguarda "avere metodi di setter non ha senso": un metodo 'add' (come quello menzionato nella domanda) può avere senso in un oggetto immutabile restituendo un nuovo oggetto con lo stato modificato. –

17

oggetti immutabili non hanno metodi setter. Periodo.

Tutti si aspettano un metodo setXyz() per avere un tipo di reso vuoto (o non restituire nulla in lingue vagamente tipizzate). Se aggiungi metodi setter al tuo oggetto immutabile, confonderà le persone e causerà brutti bug.

+1

bene che non si chiamerebbe come set(), ma non so come chiamarli. metodi addetter? :) – Elfy

+0

Anche se alcuni tra quelli "Tutti" non saranno sorpresi di ricevere un'istanza dell'oggetto del setter, per consentire il concatenamento del metodo ;-) –

+4

@Elfy Chiamali con i metodi "con". '$ obj-> withMyProp ($ x)' restituisce una nuova istanza * con * "MyProp" impostato su '$ x'. – mpen

8

A mio parere, gli oggetti dovrebbero essere immutabili per gli oggetti valore. A parte questo, non ha molti vantaggi a meno che tu non condivida il tuo oggetto su tutta la tua applicazione.

C'è qualche risposta errata qui, un oggetto immutabile può avere setter. Ecco alcune implementazioni di oggetti immutabili in PHP.

Esempio n. 1.

class ImmutableValueObject 
{ 
    private $val1; 
    private $val2; 

    public function __construct($val1, $val2) 
    { 
     $this->val1 = $val1; 
     $this->val2 = $val2; 
    } 

    public function getVal1() 
    { 
     return $this->val1; 
    } 

    public function getVal2() 
    { 
     return $this->val2; 
    } 
} 

Come si può vedere una volta istanziato non è possibile modificare alcun valore.

Esempio 2: con setters:

class ImmutableValueObject 
{ 
    private $val1; 
    private $val2; 

    public function __construct($val1, $val2) 
    { 
     $this->val1 = $val1; 
     $this->val2 = $val2; 
    } 

    public function getVal1() 
    { 
     return $this->val1; 
    } 

    public function withVal1($val1) 
    { 
     $copy = clone $this; 
     $copy->val1 = $val1; 

     return $copy; // here's the trick: you return a new instance! 
    } 

    public function getVal2() 
    { 
     return $this->val2; 
    } 

    public function withVal2($val2) 
    { 
     $copy = clone $this; 
     $copy->val2 = $val2; 

     return $copy; 
    } 
} 

V'è possibile vari implementazione e questo non è affatto un elenco esclusivo. E ricorda che con Reflection c'è sempre un modo per aggirarlo in PHP, quindi l'immutabilità è tutta nella tua testa alla fine!

Spesso è anche buona norma mettere gli oggetti immutabili come finali.

EDIT:

  • cambiato setX per withX
  • commenti su finale
+0

Dovrebbe restituire $ this; restituire effettivamente '$ copy'? –

+0

Corretto l'errore grazie per quello –

+0

"In informatica, un metodo di mutatore è un metodo utilizzato per controllare le modifiche a una variabile e sono anche ampiamente noti come metodi setter" .__ Un oggetto immutabile non può avere setter__. I suoi metodi non cambiano lo stato interno dell'oggetto. __Crea solo una nuova istanza__. È molto diverso. –

Problemi correlati