praktik terbaik untuk menginisialisasi anggota kelas di php

10

Saya punya banyak kode seperti ini di konstruktor saya: -

function __construct($params) {

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

}

Apakah lebih baik melakukan ini daripada menentukan nilai default dalam definisi properti? yaitu public $property = default_val? Kadang-kadang ada logika untuk nilai default, dan beberapa nilai default diambil dari properti lain, itulah sebabnya saya melakukan ini di konstruktor.

Haruskah saya menggunakan setter agar semua logika untuk nilai default dipisahkan?

rgvcorley
sumber

Jawaban:

8

Saya pernah berdebat filosofis semacam ini dengan diri saya sendiri sebelumnya. Di sinilah saya berdiri sebagian besar waktu meskipun saya menyadari ini adalah jawaban berdasarkan pendapat:

Satu hal yang saya lihat yang mungkin dapat membantu menjawab pertanyaan ini adalah meloloskan $ params yang mungkin atau mungkin tidak memiliki atribut / susunan anggota yang ditetapkan.

Selama bertahun-tahun saya sampai pada kesimpulan ini:

Hindari berlalunya array.

Mengapa? Yah, tidak ada cara untuk menetapkan atau memiliki nilai sentinel yang ditentukan untuk argumen yang diteruskan opsional.

Dengan kata lain, dengan kode yang Anda tentukan, Anda tidak dapat melakukan sesuatu seperti ini:

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

    $this->arg1 = $arg1;

    $this->arg2 = $arg2;

}

$ arg1 dan $ arg2 adalah argumen opsional - jika tidak lulus, masing-masing memiliki NULL dan DEFAULT_VAL - tidak perlu memeriksa secara eksplisit.

Mungkin ini agak sewenang-wenang.

Saya pikir saya mendapatkan apa yang Anda coba capai - lewat satu referensi sebagai lawan dari banyak argumen. Ini membawa saya ke kesimpulan saya berikutnya:

Jika tidak melewati variabel "atom" (string, integer, literal), maka meneruskan objek.

Ada manfaat kinerja di sini karena benda lewat dilakukan dengan referensi (meskipun array saya pikir kira-kira sama di dalam PHP).

Jadi, Anda mungkin melakukan sesuatu seperti:

function __construct(MyAwesomeObject $oArg) {

        $this->oArg = $oArg;

    }

Argumen objek yang diteruskan akan dijamin memiliki "property1", "property2" walaupun mungkin dengan nilai default sendiri.

Selain itu, di sini Anda dapat mengetikkan petunjuk dan IDE yang bagus akan secara otomatis mengisyaratkan penyelesaian kode juga.

Tapi kami segera menyadari bahwa kami memiliki ayam dan telur yang sedang terjadi: Anda membangun sebuah objek dengan argumen objek yang berlalu yang mereka sendiri butuhkan untuk membangun di beberapa titik.

Jadi bagaimana kita meninggalkan ini? Yah, saya sampai pada kesimpulan bahwa akhirnya semua kelas menyaring, karena tidak ada istilah yang lebih baik, "atom" variabel (string, float, double, ints, sumber daya yang Anda dapatkan poin saya), dan bahwa saya cenderung untuk mencoba untuk membangun semua kelas dengan tipe variabel atau objek - tetapi tidak array.

Jadi, apakah saya menjawab pertanyaan Anda? mungkin tidak tepat. Tapi saya harap saya mengilustrasikan sesuatu yang bermanfaat walaupun agak bergaya. Saya pikir kode ini sedikit lebih bersih, lebih mudah dibaca, dan lebih murah.

Sekarang, ini bukan untuk mengatakan Anda tidak harus membersihkan input Anda. Itu diskusi lain sepenuhnya.

Semoga ini membantu.

ekeyser
sumber
1
Ini adalah poin yang bagus, dan sangat berguna untuk IDE, tetapi ada terlalu banyak properti objek untuk melewatkan semuanya sebagai parameter. Jika Anda memiliki 7 argumen, 5 di antaranya adalah opsional Anda berakhir dengan hal-hal seperti new object($param1,-some default value so I can specify the next parameter-, $param3);dan Anda memiliki nilai default Anda dikodekan di beberapa tempat yang berbeda
rgvcorley
3

Meskipun saya cenderung untuk menghindari melewati array ke konstruktor, kadang-kadang saya merasa perlu untuk memproses nilai array yang masuk (seperti untuk kelas yang membaca nilai dari file konfigurasi).

Dalam kasus seperti ini, saya akan memanfaatkan fungsi array PHP untuk memastikan bahwa saya bekerja dengan apa yang saya pikir saya kerjakan:

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

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

  ...
}

Baris terakhir itu digunakan array_merge()untuk menimpa nilai apa pun $defaultsdengan nilai terkaitnya $incoming. Saya juga menggunakan array_intersect_key()untuk memastikan bahwa array yang dihasilkan tidak mengandung kunci tambahan bahwa kelas / metode tidak akan tahu bagaimana memprosesnya.


sumber
Halo, Apa kelakuannya jika $ default berisi array bukan variabel sederhana?
Pol Dellaiera
@PolDellaiera Lihat array_merge_recursive.