Best Practice für die Initialisierung von Klassenmitgliedern in PHP


10

Ich habe viel Code wie diesen in meinen Konstruktoren: -

function __construct($params) {

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

}

Ist es besser, dies zu tun, als den Standardwert in der Eigenschaftsdefinition anzugeben? dh public $property = default_val? Manchmal gibt es eine Logik für den Standardwert, und einige Standardwerte werden aus anderen Eigenschaften übernommen, weshalb ich dies im Konstruktor getan habe.

Sollte ich Setter verwenden, damit die gesamte Logik für Standardwerte getrennt ist?

Antworten:


8

Ich habe diese Art von philosophischer Debatte schon einmal mit mir selbst geführt. Hier stehe ich die meiste Zeit, obwohl mir klar ist, dass dies eine meinungsbasierte Antwort ist:

Eine Sache, die mir bei der Beantwortung der Frage helfen könnte, ist die Übergabe von $ params, für die möglicherweise Attribute / Array-Mitglieder festgelegt sind oder nicht.

Im Laufe der Jahre bin ich zu folgendem Schluss gekommen:

Vermeiden Sie das Übergeben von Arrays.

Warum? Nun, es gibt keine Möglichkeit, Sentinel-Werte für optional übergebene Argumente festzulegen oder zu definieren.

Mit anderen Worten, mit dem von Ihnen angegebenen Code können Sie so etwas nicht tun:

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

    $this->arg1 = $arg1;

    $this->arg2 = $arg2;

}

$ arg1 und $ arg2 sind optionale Argumente - wenn sie nicht übergeben werden, haben sie NULL bzw. DEFAULT_VAL - müssen nicht explizit überprüft werden.

Vielleicht scheint das irgendwie willkürlich.

Ich glaube, ich verstehe, was Sie erreichen wollen - die Übergabe einer einzigen Referenz im Gegensatz zu Tonnen von Argumenten. Dies bringt mich zu meiner nächsten Schlussfolgerung:

Wenn Sie keine "atomaren" Variablen (Zeichenfolgen, Ganzzahlen, Literale) übergeben, übergeben Sie Objekte.

Hier gibt es Leistungsvorteile, da das Übergeben von Objekten als Referenz erfolgt (obwohl Arrays meiner Meinung nach in PHP ungefähr gleich sind).

Sie könnten also etwas tun wie:

function __construct(MyAwesomeObject $oArg) {

        $this->oArg = $oArg;

    }

Das übergebene Objektargument würde dann garantiert "property1", "property2" haben, wenn auch möglicherweise mit Standardwerten selbst.

Außerdem können Sie hier einen Hinweis eingeben, und eine gute IDE schlägt auch die automatische Code-Vervollständigung korrekt vor.

Aber wir stellen schnell fest, dass ein Huhn und ein Ei im Gange sind: Sie konstruieren ein Objekt mit übergebenen Objektargumenten, die selbst irgendwann konstruiert werden müssen.

Wo bleibt uns das? Nun, ich bin zu dem Schluss gekommen, dass schließlich alle Klassen, mangels eines besseren Ausdrucks, auf "atomare" Variablen (Strings, Floats, Doubles, Ints, Ressourcen, auf die Sie meinen Punkt bringen) hinauslaufen und dass ich dazu neige, es zu versuchen um alle Klassen mit diesen Variablentypen oder Objekten zu erstellen - aber nicht mit Arrays.

Habe ich deine Frage beantwortet? wahrscheinlich nicht genau. Aber ich hoffe, ich habe etwas Nützliches, wenn auch etwas Stilistisches illustriert. Ich denke, der Code ist etwas sauberer, lesbarer und kostengünstiger.

Das soll nicht heißen, dass Sie Ihre Eingabe nicht bereinigen sollten. Das ist eine ganz andere Diskussion.

Hoffe das hilft.


1
Dies ist ein guter Punkt und sehr praktisch für IDE-Eingabeaufforderungen, aber es gibt viel zu viele Objekteigenschaften, um sie alle als Parameter zu übergeben. Wenn Sie 7 Argumente haben, von denen 5 optional sind, erhalten Sie Dinge wie new object($param1,-some default value so I can specify the next parameter-, $param3);und so haben Sie Ihre Standardwerte an mehreren verschiedenen Stellen fest codiert
rgvcorley

3

Obwohl ich es vermeide, Arrays an einen Konstruktor zu übergeben, finde ich es manchmal notwendig, einen eingehenden Array-Wert zu verarbeiten (z. B. für eine Klasse, die Werte aus einer Konfigurationsdatei liest).

In einem solchen Fall werde ich die Array-Funktionen von PHP nutzen, um sicherzustellen, dass ich mit genau dem arbeite, mit dem ich zu arbeiten glaube:

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

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

  ...
}

In dieser letzten Zeile werden array_merge()alle Werte $defaultsmit den entsprechenden Werten von überschrieben $incoming. Ich verwende auch, array_intersect_key()um sicherzustellen, dass das resultierende Array keine zusätzlichen Schlüssel enthält, die die Klasse / Methode nicht verarbeiten kann.


Hallo, wie verhält es sich, wenn $ defaults anstelle einfacher Variablen ein Array enthält?
Pol Dellaiera

@PolDellaiera Schau dir an array_merge_recursive.
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.