best practice per inizializzare i membri della classe in php

10

Ho un sacco di codice come questo nei miei costruttori: -

function __construct($params) {

    $this->property = isset($params['property']) ? $params['property'] : default_val;

}

È meglio fare questo invece di specificare il valore predefinito nella definizione della proprietà? vale a dire public $property = default_val ? A volte esiste una logica per il valore predefinito e alcuni valori predefiniti sono presi da altre proprietà, motivo per cui stavo facendo questo nel costruttore.

Devo usare i setter in modo tale che tutta la logica per i valori di default sia separata?

    
posta rgvcorley 07.04.2012 - 12:02
fonte

2 risposte

8

Ho avuto questo tipo di dibattito filosofico con me stesso prima. Ecco dove mi trovo la maggior parte del tempo anche se mi rendo conto che questa è una risposta basata sull'opinione:

Una cosa che vedo che potrebbe aiutare a rispondere alla domanda è il passaggio di $ param che possono avere o meno attributi / membri dell'array impostati.

Nel corso degli anni sono giunto a questa conclusione:

Evita il passaggio di array.

Perché? Bene, non c'è modo di impostare o avere valori sentinella definiti per gli argomenti passati opzionali.

In altre parole, con il codice che hai specificato, non puoi fare qualcosa del genere:

function __construct($arg1 = NULL, $arg2 = DEFAULT_VAL) {

    $this->arg1 = $arg1;

    $this->arg2 = $arg2;

}

$ arg1 e $ arg2 sono argomenti facoltativi - se non passati hanno rispettivamente NULL e DEFAULT_VAL - non c'è bisogno di verificare esplicitamente.

Forse sembra un po 'arbitrario.

Penso di ottenere ciò che stai cercando di ottenere - il passaggio di un singolo riferimento invece di tonnellate di argomenti. Questo mi porta alla mia prossima soluzione:

Se non passa le variabili "atomiche" (stringhe, interi, letterali) quindi passa gli oggetti.

Qui ci sono dei vantaggi in termini di prestazioni dato che il passaggio degli oggetti avviene per riferimento (sebbene gli array che ritengo siano più o meno gli stessi all'interno di PHP).

Quindi potresti fare qualcosa del tipo:

function __construct(MyAwesomeObject $oArg) {

        $this->oArg = $oArg;

    }

L'argomento oggetto passato dovrebbe quindi avere "proprietà1", "proprietà2" anche se probabilmente con valori predefiniti stessi.

Inoltre, qui puoi digitare hint e un buon IDE eseguirà correttamente anche il completamento del codice.

Ma ci rendiamo presto conto che abbiamo un problema con un pollo e un uovo: stai costruendo un oggetto con argomenti oggetto passati che a un certo punto devono essere costruiti.

Quindi, dove ci lascia questo? Bene, sono giunto alla conclusione che alla fine tutte le classi distillano fino a, per mancanza di un termine migliore, variabili "atomiche" (stringhe, float, doppi, intarsi, risorse si ottiene il mio punto), e che io tendo a provare per costruire tutte le classi con quei tipi o oggetti variabili - ma non con gli array.

Così ho risposto alla tua domanda? probabilmente non esattamente. Ma spero di aver illustrato qualcosa di utile anche se un po 'stilistico. Penso che il codice sia un po 'più pulito, più leggibile e meno costoso.

Ora, questo non vuol dire che non dovresti disinfettare il tuo contributo. Questa è un'altra discussione completamente.

Spero che questo aiuti.

    
risposta data 08.04.2012 - 18:55
fonte
3

Sebbene tendo ad evitare di passare array a un costruttore, a volte trovo necessario elaborare un valore di array in ingresso (come per una classe che legge valori da un file di configurazione).

In un caso come questo, approfitterò delle funzioni di array di PHP per assicurarmi di lavorare esattamente con ciò che penso stia lavorando:

public function import( array $incoming )
{
  $defaults = array(
      'foo' => DEFAULT_FOO
    , 'bar' => DEFAULT_BAR
    ...
  );

  $values = array_merge($defaults, array_intersect_key($incoming, $defaults));

  ...
}

L'ultima riga utilizza array_merge() per sovrascrivere qualsiasi valore in $defaults con i valori corrispondenti da $incoming . Uso anche array_intersect_key() per garantire che l'array risultante non contenga chiavi aggiuntive che la classe / metodo non saprebbe come elaborare.

    
risposta data 08.04.2012 - 19:47
fonte

Leggi altre domande sui tag