Konstruktor

Overload konstruktor, perantai this, dan konstruksi default.

Daftar isi

Topik ini membahas konstruktor, yaitu metode khusus yang dijalankan operator new setiap kali sebuah object dibuat. Materinya mencakup overload konstruktor, perantai konstruktor dengan kata kunci this, serta perilaku konstruksi default ketika kelas tidak mendeklarasikan konstruktor apa pun. Setelah topik ini diselesaikan, inisialisasi object dapat dikelola dalam beberapa varian tanpa menduplikasi penugasannya.

Konstruktor dan overload-nya#

Konstruktor adalah metode yang namanya sama dengan nama kelasnya dan tidak memiliki tipe nilai balik. Konstruktor dijalankan secara otomatis oleh new, sehingga inisialisasi yang wajib dilakukan, misalnya mengisi field dengan data awal, ditempatkan di dalam tubuhnya. Konstruktor boleh memiliki parameter, dan parameter itulah yang menentukan data apa yang harus disediakan setiap kali object dibuat.

Overload (overloading, menyediakan beberapa versi anggota dengan daftar parameter yang berbeda) membuat sebuah kelas dapat dikonstruksi lewat lebih dari satu cara. Kompilator memilih versi yang digunakan dengan mencocokkan argumen pemanggilan terhadap daftar parameter setiap overload. Program berikut mendeklarasikan tiga konstruktor untuk kelas Sensor yang masing-masing menerima data berbeda.

csharp Program.cs
// Program: tiga overload konstruktor kelas Sensor yang dirantai dengan this.
Sensor a = new Sensor("Ruang Server", 24);
Sensor b = new Sensor("Gudang");
Sensor c = new Sensor();

a.Tampilkan();
b.Tampilkan();
c.Tampilkan();

class Sensor
{
    public string Lokasi;
    public int Suhu;

    public Sensor(string lokasi, int suhu)
    {
        Lokasi = lokasi;
        Suhu = suhu;
    }

    public Sensor(string lokasi) : this(lokasi, 0)
    {
    }

    public Sensor() : this("Tidak diketahui")
    {
    }

    public void Tampilkan()
    {
        Console.WriteLine($"{Lokasi}: {Suhu} derajat");
    }
}
text Keluaran
Ruang Server: 24 derajat
Gudang: 0 derajat
Tidak diketahui: 0 derajat

Tiga object pada program di atas dibuat melalui jalur konstruksi yang berbeda, tetapi hasil akhirnya sama, yaitu field Lokasi dan Suhu terisi sebelum metode apa pun dipanggil. a dikonstruksi dengan data lengkap, b hanya menyediakan lokasi, sedangkan c tidak menyediakan apa pun dan diberi nilai pengganti oleh konstruktor tanpa parameter. Ketiga jalur itu bermuara pada konstruktor dua parameter, karena dua overload lainnya merantai ke sana.

Perantai konstruktor dengan this#

Satu konstruktor boleh memanggil konstruktor lain dari kelas yang sama dengan menyertakan : this(...) setelah daftar parameternya. Konstruktor yang dirantai dijalankan terlebih dahulu, kemudian barulah tubuh konstruktor pemanggilnya. Pada program di atas, Sensor(string lokasi) merantai this(lokasi, 0) sehingga penugasan field cukup ditulis satu kali di konstruktor dua parameter, dan Sensor() merantai this("Tidak diketahui") sehingga berantai dua tingkat.

Perantai ini menjaga satu aturan penting, yaitu inisialisasi inti berada di satu tempat. Perubahan aturan pengisian field cukup dilakukan pada satu konstruktor, dan seluruh jalur konstruksi lainnya mengikutinya secara otomatis. Tanpa perantai, setiap overload harus mengulang penugasan yang sama, dan salah satu yang terlewat menghasilkan object dengan inisialisasi tidak lengkap.

Urutan inisialisasi perlu dicermati karena field boleh memiliki inisialisernya sendiri. Inisialisator field dijalankan lebih dahulu, kemudian tubuh konstruktor dijalankan dan boleh menimpanya. Kelalaian memperhitungkan urutan ini kerap menghasilkan nilai awal yang tampak sulit dijelaskan.

csharp Contoh: inisialisator field berjalan sebelum tubuh konstruktor
var penghitung = new Penghitung();
Console.WriteLine(penghitung.Langkah);

class Penghitung
{
    public int Langkah = 10;

    public Penghitung()
    {
        Langkah += 5;
    }
}
text Keluaran
15

Field Langkah bernilai 10 karena inisialisatornya, lalu tubuh konstruktor menambahkannya dengan 5, sehingga hasil akhirnya 15. Urutan yang sama berlaku pada rantai this(...), yaitu inisialisator field dijalankan lebih dahulu, diikuti tubuh konstruktor sasaran perantai, dan tubuh konstruktor pemanggil paling akhir. Apabila tubuh konstruktor tidak menimpa nilai awalnya, nilai inisialisator itulah yang tetap terpakai.

Konstruksi default#

Kelas yang tidak mendeklarasikan konstruktor apa pun tetap dapat dibuat dengan new Kelas(). Kompilator menyediakan konstruktor tanpa parameter secara otomatis, dan konstruktor tersebut mengisi setiap field dengan nilai default tipenya, yaitu 0 untuk angka, false untuk bool, dan null untuk tipe reference. Konstruksi seperti ini disebut konstruksi default karena tidak ada inisialisasi khusus yang terjadi.

Konstruktor otomatis itu hanya ada selama tidak ada satu konstruktor pun yang dideklarasikan. Begitu sebuah konstruktor berparameter dideklarasikan, seperti pada kelas Sensor di atas, pemanggilan tanpa argumen ditolak. Perubahan perilaku ini sering mengejutkan pemanggil lama yang terbiasa membuat object tanpa argumen.

csharp Contoh: pemanggilan tanpa argumen setelah konstruktor berparameter ada
// tidak-dijalankan
Sensor c = new Sensor();

Kompilator menolak baris tersebut dengan error CS7036: There is no argument given that corresponds to the required parameter. Perbaikannya ada dua, yaitu menyediakan argumen yang cocok dengan salah satu overload atau mendeklarasikan kembali konstruktor tanpa parameter yang merantai this(...), sebagaimana dilakukan program pada bagian pertama. Pesan errornya menunjuk parameter yang tidak menerima argumen, sehingga overload yang dimaksud langsung terlihat.

Nilai default yang diisi konstruksi default jarang menjadi keadaan awal yang dimaksudkan. Field Lokasi bertipe string yang dibiarkan bernilai null, misalnya, menyimpan masalah untuk metode yang memakainya, sehingga konstruksi default lebih tepat dipandang sebagai jaring pengaman kompilator daripada pola yang diikuti. Konstruktor eksplisit memberi kesempatan menetapkan nilai awal yang bermakna sejak baris pertama keberadaan objectnya.

Kesalahan umum#

  • Mengharapkan new Kelas() tetap berfungsi setelah konstruktor berparameter dideklarasikan. Konstruksi default hilang bersamaan dengan deklarasi tersebut, sehingga muncul error CS7036. Tambahkan konstruktor tanpa parameter yang merantai this(...) atau sediakan argumen yang cocok dengan salah satu overload.
  • Menduplikasi penugasan di setiap overload. Penugasan yang disalin ke banyak konstruktor mudah menyimpang ketika satu salinan terlewat saat disunting. Gunakan perantai this(...) agar inisialisasi inti berada di satu konstruktor saja.
  • Mengisi nilai awal di dua tempat tanpa disadari. Inisialisator field dijalankan lebih dahulu, kemudian tubuh konstruktor boleh menimpanya, sehingga penugasan yang tumpang tindih menyulitkan penelusuran. Tentukan satu tempat bagi setiap nilai awal, misalnya hanya di inisialisator atau hanya di tubuh konstruktor.

Ringkasan#

  • Konstruktor dijalankan otomatis oleh new dan menjadi tempat inisialisasi wajib sebuah object.
  • Overload menyediakan beberapa cara konstruksi, dan kompilator memilih versinya dengan mencocokkan argumen pemanggilan terhadap daftar parameter.
  • Perantai this(...) menjalankan konstruktor sasaran terlebih dahulu, sehingga inisialisasi inti cukup ditulis satu kali.
  • Konstruktor tanpa parameter dari kompilator hanya tersedia bila tidak ada konstruktor lain yang dideklarasikan, dan fieldnya diisi nilai default tipenya.

Referensi#