Apakah ada alasan untuk melakukan semua pekerjaan objek dalam konstruktor?


49

Izinkan saya mengawali ini dengan mengatakan ini bukan kode saya atau kode rekan kerja saya. Bertahun-tahun yang lalu ketika perusahaan kami lebih kecil, kami memiliki beberapa proyek yang perlu kami lakukan sehingga kami tidak memiliki kapasitas untuk itu, jadi mereka di-outsource. Sekarang, saya tidak menentang outsourcing atau kontraktor pada umumnya, tetapi basis kode yang mereka hasilkan adalah sejumlah besar WTF. Yang sedang berkata, itu (kebanyakan) bekerja, jadi saya kira itu dalam 10% teratas dari proyek outsourcing yang pernah saya lihat.

Seiring berkembangnya perusahaan kami, kami telah mencoba mengambil alih lebih banyak dari pengembangan kami secara langsung. Proyek khusus ini mendarat di pangkuan saya jadi saya sudah membahasnya, membersihkannya, menambahkan tes, dll.

Ada satu pola yang saya lihat berulang-ulang dan tampaknya sangat mengerikan sehingga saya bertanya-tanya apakah mungkin ada alasan dan saya tidak melihatnya. Pola adalah objek tanpa metode publik atau anggota, hanya konstruktor publik yang melakukan semua pekerjaan objek.

Misalnya, (kodenya di Jawa, jika itu penting, tapi saya harap ini menjadi pertanyaan yang lebih umum):

public class Foo {
  private int bar;
  private String baz;

  public Foo(File f) {
    execute(f);
  }

  private void execute(File f) {
     // FTP the file to some hardcoded location, 
     // or parse the file and commit to the database, or whatever
  }
}

Jika Anda bertanya-tanya, jenis kode ini sering disebut dengan cara berikut:

for(File f : someListOfFiles) {
   new Foo(f);
}

Sekarang, saya telah diajarkan sejak lama bahwa objek instantiated dalam satu lingkaran pada umumnya adalah ide yang buruk, dan bahwa konstruktor harus melakukan pekerjaan minimum. Melihat kode ini sepertinya akan lebih baik untuk menjatuhkan konstruktor dan membuat executemetode statis publik.

Saya memang bertanya kepada kontraktor mengapa itu dilakukan dengan cara ini, dan respons yang saya dapatkan adalah "Kami dapat mengubahnya jika Anda mau". Yang tidak terlalu membantu.

Ngomong-ngomong, apakah ada alasan untuk melakukan hal seperti ini, dalam bahasa pemrograman apa pun, atau apakah ini sekadar pengajuan ke Daily WTF?


18
Sepertinya saya ditulis oleh pengembang yang tahu tentang public static void main(string[] args)dan yang pernah mendengar objek, kemudian mencoba untuk menumbuknya bersama.
Andy Hunt

Jika Anda tidak pernah dipanggil lagi, Anda harus melakukannya di sana. Banyak kerangka kerja modern untuk mis. Injeksi ketergantungan memerlukan biji yang harus dibuat, mengatur properti dan MAKA dipanggil, dan kemudian Anda tidak dapat menggunakan pekerja berat ini.

4
Pertanyaan terkait: Adakah masalah dengan melakukan pekerjaan utama kelas dalam konstruktornya? . Yang ini sedikit berbeda, karena instance yang dibuat digunakan sesudahnya.
sleske

sebuah bacaan yang bagus tentang Memisahkan Penggunaan objek dari Konstruksi
Songo

Saya tidak benar-benar ingin mengembangkan ini menjadi jawaban penuh, tetapi izinkan saya katakan saja: ada skenario, di mana ini bisa dibilang dapat diterima. Yang ini sangat jauh dari itu. Di sini suatu objek dipakai tanpa benar-benar membutuhkan objek. Berbeda dengan itu, jika Anda membuat semacam struktur data dari file XML, memulai parsing dari konstruktor tidak sepenuhnya mengerikan. Sebenarnya dalam bahasa yang memungkinkan konstruktor kelebihan muatan, bukan apa-apa saya akan membunuh Anda sebagai pengelola;)
back2dos

Jawaban:


60

Ok, turun daftar:

Saya sudah lama diajarkan bahwa objek instantiated dalam satu lingkaran umumnya adalah ide yang buruk

Tidak dalam bahasa apa pun yang saya gunakan.

Dalam C itu adalah ide yang baik untuk mendeklarasikan variabel Anda di muka, tetapi itu berbeda dari apa yang Anda katakan. Mungkin sedikit lebih cepat jika Anda mendeklarasikan objek di atas loop dan menggunakannya kembali, tetapi ada banyak bahasa di mana peningkatan kecepatan ini akan menjadi tidak berarti (dan mungkin beberapa kompiler di luar sana yang melakukan optimasi untuk Anda :)).

Secara umum, jika Anda membutuhkan objek dalam satu lingkaran, buat satu.

konstruktor harus melakukan pekerjaan minimum

Konstruktor harus instantiate bidang objek dan melakukan inisialisasi lain yang diperlukan untuk membuat objek siap digunakan. Ini umumnya berarti konstruktor kecil, tetapi ada skenario di mana ini akan menjadi sejumlah besar pekerjaan.

apakah pernah ada alasan untuk melakukan hal seperti ini, dalam bahasa pemrograman apa pun, atau apakah ini hanya penyerahan lain kepada Daily WTF?

Ini adalah pengiriman ke Daily WTF. Memang, ada hal-hal buruk yang dapat Anda lakukan dengan kode. Masalahnya adalah bahwa penulis memiliki kesalahpahaman yang luas tentang kelas apa dan bagaimana menggunakannya. Secara khusus, inilah yang saya lihat salah dengan kode ini:

  • Penyalahgunaan kelas: Kelas ini pada dasarnya bertindak seperti fungsi. Seperti yang Anda sebutkan, itu harus diganti dengan fungsi statis, atau fungsi tersebut harus diimplementasikan di kelas yang memanggilnya. Tergantung pada apa yang dilakukannya dan di mana ia digunakan.
  • Overhead kinerja: Bergantung pada bahasa, membuat objek bisa lebih lambat daripada memanggil fungsi.
  • Kebingungan umum: Biasanya membingungkan bagi programmer bagaimana menggunakan kode ini. Tanpa melihatnya digunakan, tidak ada yang akan tahu bagaimana penulis bermaksud menggunakan kode yang dimaksud.

Terimakasih atas tanggapan Anda. Mengacu pada "instantiating objek dalam satu lingkaran", ini adalah sesuatu yang memperingatkan banyak alat analisis statis, dan saya juga mendengarnya dari beberapa profesor perguruan tinggi. Memang, itu mungkin penahanan dari tahun 90-an ketika kinerja hit lebih besar. Tentu saja, jika Anda membutuhkannya, lakukanlah, tetapi saya terkejut mendengar sudut pandang yang berlawanan. Terima kasih telah memperluas wawasan saya.
Kane

8
Instantiasi objek dalam satu lingkaran adalah bau kode minor; Anda harus melihatnya dan bertanya "apakah saya benar-benar perlu membuat instance objek ini beberapa kali?". Jika Anda instantiasi objek yang sama dengan data yang sama dan menyuruhnya melakukan hal yang sama, Anda akan menghemat siklus (dan menghindari meronta-ronta memori) dengan instantiate sekali dan kemudian hanya mengulangi instruksi dengan perubahan inkremental apa pun yang mungkin diperlukan untuk menyatakan objek . Namun, jika Anda, misalnya, membaca aliran data dari DB atau input lain dan membuat serangkaian objek untuk menyimpan data itu, tentu saja instantiate.
KeithS

3
Versi singkat: Jangan gunakan instantiasi objek seperti itu adalah fungsi.
Erik Reppen

27

Bagi saya, ini sedikit mengejutkan ketika Anda mendapatkan objek melakukan banyak pekerjaan di konstruktor, jadi hanya pada itu saya akan merekomendasikan menentangnya (prinsip kejutan paling tidak).

Upaya contoh yang baik :

Saya tidak yakin apakah penggunaan ini anti-pola, tetapi dalam C # Saya telah melihat kode yang sesuai dengan (contoh yang agak dibuat-buat):

using (ImpersonationContext administrativeContext = new ImpersonationContext(ADMIN_USER))
{
    // Perform actions here under the administrator's security context
}
// We're back to "normal" privileges here

Dalam hal ini, ImpersonationContextkelas melakukan semua pekerjaannya di konstruktor dan metode Buang. Itu mengambil keuntungan dari pernyataan C # using, yang cukup dipahami dengan baik oleh pengembang C #, dan dengan demikian menjamin bahwa pengaturan yang terjadi dalam konstruktor dibatalkan setelah kita berada di luar usingpernyataan, bahkan jika pengecualian terjadi. Ini mungkin penggunaan terbaik yang pernah saya lihat untuk ini (yaitu "bekerja" di konstruktor), meskipun saya masih tidak yakin saya akan menganggapnya "baik". Dalam hal ini, itu cukup jelas, fungsional dan cepat.

Contoh pola yang baik dan serupa akan menjadi pola perintah . Anda pasti tidak mengeksekusi logika di konstruktor di sana, tetapi itu serupa dalam arti bahwa seluruh kelas setara dengan doa metode (termasuk parameter yang diperlukan untuk memanggil metode). Dengan cara ini, informasi pemanggilan metode dapat diserialisasi atau diteruskan untuk penggunaan selanjutnya, yang sangat berguna. Mungkin kontraktor Anda mencoba sesuatu yang serupa, walaupun saya sangat meragukannya.

Komentar pada contoh Anda:

Saya akan mengatakan itu adalah anti-pola yang sangat pasti. Ia tidak menambahkan apa-apa, bertentangan dengan apa yang diharapkan, dan melakukan pemrosesan yang terlalu lama di konstruktor (FTP dalam konstruktor? WTF memang, meskipun saya kira orang telah dikenal untuk memanggil layanan web dengan cara ini).

Saya berjuang untuk menemukan kutipan, tetapi buku Grady Booch "Object Solutions" memiliki anekdot tentang tim pengembang C yang beralih ke C ++. Rupanya mereka telah melalui pelatihan, dan diberitahu oleh manajemen bahwa mereka benar-benar harus melakukan hal-hal yang "berorientasi objek". Dibawa ke dalam untuk mencari tahu apa yang salah, penulis menggunakan alat metrik kode, dan menemukan bahwa jumlah rata-rata metode per kelas tepat 1, dan variasi kalimat "Do It". Saya harus mengatakan, saya belum pernah mengalami masalah khusus ini sebelumnya, tetapi ternyata itu bisa menjadi gejala orang dipaksa untuk membuat kode berorientasi objek, tanpa benar-benar mengerti bagaimana melakukannya, dan mengapa.


1
Contoh Anda yang baik adalah contoh dari Alokasi Sumber Daya adalah Inisialisasi . Ini adalah pola yang disarankan dalam C ++ karena membuatnya lebih mudah untuk menulis kode pengecualian-aman. Saya tidak tahu apakah itu mengarah ke C #. (Dalam hal ini "sumber daya" yang dialokasikan adalah hak administratif.)
zwol

@ Zack Saya tidak pernah memikirkannya dalam istilah-istilah itu, meskipun saya sudah mengetahui RAII di C ++. Di dunia C #, ini disebut sebagai pola Disposable, dan sangat disarankan untuk apa pun yang memiliki (biasanya tidak dikelola) sumber daya untuk dibebaskan setelah masa pakainya. Perbedaan utama pada contoh ini adalah Anda biasanya tidak melakukan operator mahal dalam konstruktor. Misalnya metode Open () SqlConnection masih perlu dipanggil setelah konstruktor.
Daniel B

14

Tidak.

Jika semua pekerjaan dilakukan di konstruktor itu berarti objek itu tidak pernah dibutuhkan sejak awal. Kemungkinan besar, kontraktor hanya menggunakan objek untuk modularitas. Dalam hal itu, kelas non-instantiated dengan metode statis akan mendapatkan manfaat yang sama tanpa membuat instance objek yang berlebihan.

Hanya ada satu kasus di mana melakukan semua pekerjaan dalam konstruktor objek dapat diterima. Saat itulah tujuan objek secara khusus untuk mewakili identitas unik jangka panjang, daripada melakukan pekerjaan. Dalam kasus seperti itu, objek akan disimpan untuk alasan selain melakukan pekerjaan yang bermakna. Misalnya, contoh tunggal.


7

Saya tentu saja membuat banyak kelas yang melakukan banyak pekerjaan untuk menghitung sesuatu di konstruktor, tetapi objeknya tidak berubah, sehingga membuat hasil perhitungan itu tersedia melalui properti, dan kemudian tidak pernah melakukan hal lain. Itu kekekalan normal dalam aksi.

Saya pikir yang aneh di sini adalah memasukkan kode dengan efek samping ke dalam konstruktor. Membangun objek dan membuangnya tanpa mengakses properti atau metode terlihat aneh (tapi setidaknya dalam hal ini cukup jelas bahwa ada sesuatu yang sedang terjadi).

Ini akan lebih baik jika fungsi dipindahkan ke metode publik, dan kemudian memiliki instance dari kelas yang disuntikkan, kemudian minta for loop memanggil metode tersebut berulang kali.


4

Apakah ada alasan untuk melakukan semua pekerjaan objek dalam konstruktor?

Tidak.

  • Konstruktor tidak boleh memiliki efek samping.
    • Apa pun selain inisialisasi bidang pribadi harus dilihat sebagai efek samping.
    • Seorang konstruktor dengan efek samping menghancurkan Single-Responsibilty-Principle (SRP) dan berjalan berlawanan dengan semangat pemrograman berorientasi objek (OOP).
  • Konstruktor harus ringan dan tidak boleh gagal.
    • Misalnya, saya selalu ngeri ketika saya melihat blok try-catch di dalam sebuah konstruktor. Konstruktor tidak boleh membuang pengecualian atau kesalahan log.

Seseorang dapat dengan wajar mempertanyakan pedoman ini dan berkata, "Tapi saya tidak mengikuti aturan ini, dan kode saya berfungsi dengan baik!" Untuk itu, saya akan menjawab, "Yah, itu mungkin benar, sampai tidak."

  • Pengecualian dan kesalahan di dalam konstruktor sangat tidak terduga. Kecuali mereka diperintahkan untuk melakukannya, programmer masa depan tidak akan cenderung untuk mengelilingi panggilan konstruktor ini dengan kode defensif.
  • Jika ada yang gagal dalam produksi, jejak tumpukan yang dihasilkan mungkin sulit diurai. Bagian atas tumpukan jejak mungkin menunjuk ke panggilan konstruktor, tetapi banyak hal terjadi di konstruktor, dan itu mungkin tidak menunjuk ke LOC aktual yang gagal.
    • Saya telah mem-parsing banyak jejak .NET stack di mana ini terjadi.

1
"Kecuali mereka diperintahkan untuk melakukannya, programmer masa depan tidak akan cenderung untuk mengelilingi panggilan konstruktor ini dengan kode defensif." - Poin bagus.
Graham

2

Tampaknya bagi saya bahwa orang yang melakukan ini sedang mencoba untuk meretas batasan Jawa yang tidak memungkinkan untuk melewati fungsi sebagai warga negara kelas satu. Setiap kali Anda harus melewati suatu fungsi, Anda harus membungkusnya di dalam kelas dengan metode suka applyatau mirip.

Jadi saya kira dia hanya menggunakan jalan pintas dan langsung menggunakan kelas sebagai pengganti fungsi. Setiap kali Anda ingin menjalankan fungsi, Anda hanya instantiate kelas.

Ini jelas bukan pola yang baik, setidaknya karena kami di sini mencoba mencari tahu, tapi saya kira itu mungkin cara paling tidak tepat untuk melakukan sesuatu yang mirip dengan pemrograman fungsional di Jawa.


3
Saya cukup yakin programmer khusus ini belum pernah mendengar ungkapan 'pemrograman fungsional'.
Kane

Saya tidak berpikir bahwa programmer berusaha membuat abstraksi penutupan. Setara Jawa akan memerlukan metode abstrak (perencanaan untuk kemungkinan) polimorfisme. Bukan bukti di sini.
Kevin A. Naudé

1

Bagi saya aturan praktis adalah tidak melakukan apa pun di konstruktor, kecuali untuk menginisialisasi variabel anggota. Alasan pertama untuk itu adalah membantu untuk mengikuti prinsip SRP, karena biasanya proses inisialisasi yang panjang merupakan indikasi bahwa kelas melakukan lebih dari yang seharusnya, dan inisialisasi harus dilakukan di suatu tempat di luar kelas. Alasan kedua adalah bahwa dengan cara ini hanya parameter yang diperlukan yang dilewati, sehingga Anda membuat kode yang lebih sedikit digabungkan. Konstruktor dengan inisialisasi yang rumit biasanya membutuhkan parameter yang hanya digunakan untuk membangun objek lain, tetapi yang tidak digunakan oleh kelas asli.


1

Saya akan menentang arus di sini - dalam bahasa di mana semuanya harus berada dalam beberapa kelas DAN Anda tidak dapat memiliki kelas statis, Anda dapat mengalami situasi di mana Anda memiliki sedikit fungsionalitas terisolasi yang perlu taruh di suatu tempat dan tidak cocok dengan apa pun. Pilihan Anda adalah kelas utilitas yang mencakup berbagai bit fungsionalitas yang tidak terkait, atau kelas yang pada dasarnya hanya melakukan hal yang satu ini.

Jika Anda hanya memiliki satu bit seperti ini, maka kelas statis Anda adalah kelas spesifik Anda. Jadi, Anda memiliki konstruktor yang melakukan semua pekerjaan, atau fungsi tunggal yang melakukan semua pekerjaan. Keuntungan melakukan segala sesuatu di konstruktor adalah bahwa hal itu terjadi hanya sekali, memungkinkan Anda untuk menggunakan bidang pribadi, properti, dan metode tanpa khawatir mereka akan digunakan kembali atau threading. Jika Anda memiliki konstruktor / metode, Anda mungkin tergoda untuk membiarkan parameter diteruskan ke metode tunggal, tetapi jika Anda menggunakan bidang pribadi atau properti yang memperkenalkan potensi masalah threading.

Bahkan dengan kelas utilitas, kebanyakan orang tidak akan berpikir untuk memiliki kelas statis bersarang (dan itu mungkin tidak mungkin tergantung pada bahasanya).

Pada dasarnya ini adalah cara yang relatif dapat dipahami untuk mengisolasi perilaku dari sisa sistem, dalam apa yang diizinkan oleh bahasa, sambil tetap memungkinkan Anda untuk mengambil keuntungan dari sebanyak mungkin bahasa.

Terus terang saya akan menjawab sebanyak yang kontraktor Anda lakukan, itu adalah penyesuaian kecil untuk mengubahnya menjadi dua panggilan, tidak ada banyak yang merekomendasikan satu di atas yang lain. Apa dis / advatanges ada, mungkin lebih hipotetis daripada yang sebenarnya, mengapa mencoba untuk membenarkan keputusan ketika itu tidak masalah dan mungkin tidak begitu banyak diputuskan hanya sebagai tindakan default?


1

Ada pola-pola umum dalam bahasa di mana fungsi dan kelas lebih banyak hal yang sama, seperti Python, di mana orang menggunakan objek pada dasarnya menjadi fungsi dengan efek samping terlalu banyak atau dengan beberapa objek bernama dikembalikan.

Dalam hal ini, sebagian besar, jika tidak semua pekerjaan dapat dilakukan dalam konstruktor, karena objek itu sendiri hanyalah pembungkus di sekitar satu bundel pekerjaan, dan tidak ada alasan yang baik untuk memasukkannya ke dalam fungsi yang terpisah. Sesuatu seperti

var parser = XMLParser()
var x = parser.parse(string)
string a = x.LookupTag(s)

benar-benar tidak lebih baik daripada

 var x = ParsedXML(string)
 string a = x.LookupTag(s)

Alih-alih langsung memiliki efek samping, Anda dapat memanggil objek untuk menegakkan efek samping pada isyarat, yang memberi Anda visibilitas yang lebih baik. Jika saya akan memiliki efek samping yang buruk pada suatu objek, saya dapat melakukan semua pekerjaan saya dan kemudian melewati objek saya akan berdampak buruk dan melakukan kerusakan saya untuk itu. Mengidentifikasi objek dan mengisolasi panggilan dengan cara ini lebih jelas daripada melewatkan beberapa objek tersebut ke suatu fungsi sekaligus.

x.UpdateView(v)

Anda dapat membuat beberapa nilai pengembalian melalui pengakses pada objek. Semua pekerjaan sudah selesai, tetapi saya ingin semuanya dalam konteks, dan saya tidak benar-benar ingin meneruskan banyak referensi ke fungsi saya.

var x = new ComputeStatistics(inputFile)
int max = x.MaxOptions;
int mean = x.AverageOption;
int sd = x.StandardDeviation;
int k = x.Kurtosis;
...

Jadi sebagai programmer Python / C # bersama, ini sepertinya tidak aneh bagi saya.


Saya perlu mengklarifikasi bahwa contoh yang diberikan tetap menyesatkan. Dalam contoh tanpa aksesor dan tanpa nilai balik, ini mungkin masih ada. Mungkin asli memberikan pengembalian debug atau sesuatu.
Jon Jay Obermark

1

Satu kasus muncul di pikiran di mana konstruktor / penghancur melakukan semua pekerjaan:

Kunci. Anda biasanya tidak pernah berinteraksi dengan kunci selama masa pakainya. Arsitektur penggunaan C # baik untuk menangani kasus seperti itu tanpa secara eksplisit merujuk pada destruktor. Tidak semua kunci diimplementasikan dengan cara ini.

Saya juga telah menulis apa yang berjumlah sedikit kode konstruktor untuk menambal bug perpustakaan runtime. (Sebenarnya memperbaiki kode akan menyebabkan masalah lain.) Tidak ada destruktor karena tidak perlu membatalkan tambalan.


-1

Saya setuju dengan AndyBursh. Sepertinya ada sedikit masalah pengetahuan.

Namun penting untuk menyebutkan kerangka kerja seperti NHibernate yang mengharuskan Anda hanya untuk kode dalam konstruktor (saat membuat kelas peta). Namun ini bukan batasan kerangka kerja, itu hanya apa yang Anda butuhkan. Ketika datang ke refleksi, konstruktor itu satu-satunya metode yang akan selalu ada (walaupun mungkin pribadi) dan ini mungkin membantu jika Anda harus memanggil metode kelas secara dinamis.


-4

"Aku sudah lama diajari bahwa objek instantiated dalam satu lingkaran pada umumnya adalah ide yang buruk"

Ya, mungkin Anda mengingat mengapa kami membutuhkan StringBuilder.

Ada dua sekolah di Jawa.

Pembangun dipromosikan oleh yang pertama , yang mengajarkan kita untuk menggunakan kembali (karena berbagi = identitas ke efisiensi). Namun, pada awal tahun 2000 saya mulai membaca bahwa membuat objek di Jawa sangat murah (dibandingkan dengan C ++) dan GC sangat efisien sehingga penggunaan kembali tidak berharga dan satu-satunya hal yang penting adalah produktivitas programmer. Untuk produktivitas, ia harus menulis kode yang dapat dikelola, yang berarti modularisasi (alias mempersempit ruang lingkup). Begitu,

ini buruk

byte[] array = new byte[kilos or megas]
for_loop:
  use(array)

ini bagus.

for_loop:
  byte[] array = new byte[kilos or megas]
  use(array)

Saya mengajukan pertanyaan ini ketika forum.java.sun ada, dan orang-orang setuju bahwa mereka akan lebih suka mendeklarasikan array sesempit mungkin.

Programmer java modern tidak pernah ragu untuk mendeklarasikan kelas baru atau membuat objek. Dia didorong untuk melakukannya. Java memberikan semua alasan untuk melakukannya, dengan gagasan bahwa "semuanya adalah objek" dan penciptaan yang murah.

Lebih jauh, gaya pemrograman perusahaan modern adalah, ketika Anda perlu menjalankan suatu tindakan, Anda membuat kelas khusus (atau bahkan lebih baik, sebuah kerangka kerja) yang akan menjalankan tindakan sederhana itu. Good Java IDEs, itu membantu di sini. Mereka menghasilkan banyak omong kosong secara otomatis, seperti bernafas.

Jadi, saya pikir objek Anda tidak memiliki pola Builder atau Factory. Tidak layak membuat instance secara langsung, oleh konstruktor. Kelas pabrik khusus untuk setiap objek Anda disarankan.

Sekarang, ketika pemrograman fungsional mulai dimainkan, membuat objek menjadi lebih sederhana. Anda akan membuat objek di setiap langkah sebagai bernafas, tanpa menyadarinya. Jadi, saya berharap kode Anda akan menjadi lebih "efisien" di era baru

"Jangan lakukan apa pun di konstruktor Anda. Ini hanya untuk inisialisasi"

Secara pribadi, saya tidak melihat alasan dalam pedoman ini. Saya menganggapnya sebagai metode lain. Kode anjak keluar diperlukan hanya ketika Anda dapat membagikannya.


3
penjelasannya tidak terstruktur dengan baik dan sulit diikuti. Anda hanya pergi ke mana-mana dengan pernyataan yang dapat diperebutkan yang tidak memiliki tautan ke konteks.
New Alexandria

Pernyataan yang benar-benar dapat diperebutkan adalah "Konstruktor harus membuat instance bidang objek dan melakukan inisialisasi lainnya yang diperlukan untuk membuat objek siap digunakan". Ceritakan kepada kontributor paling populer.
Val
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.