Topik ini membahas pendefinisian tipe baru melalui kelas pada Carbon, mulai dari field penyusun data, pembuatan instance melalui nilai struct, hingga metode dengan parameter self. Pembahasan juga menyentuh kontrol akses dan metode yang mengubah isi instance sebagaimana ditetapkan dokumen desain, lengkap dengan status dukungan interpreter Explorer. Setelah topik ini, tipe data dengan perilaku terkait dapat didefinisikan dan dijalankan di Compiler Explorer.
Mendefinisikan kelas dan field#
Kata kunci class mendefinisikan tipe nominal, yaitu tipe yang berdiri dengan nama sendiri dan tidak sekadar gabungan tipe lain. Anggota data sebuah kelas dideklarasikan dengan var di dalam badan kelas, dan dokumen desain menyebut anggota instance tersebut field. Field menentukan tata letak data setiap instance, sehingga sebuah kelas Titik dengan dua field bertipe i32 membawa dua bilangan bulat pada setiap objeknya. Nilai awal field juga dapat dituliskan, misalnya var text: String = "default";, dan nilai itu digunakan apabila pembuatan instance tidak menyediakan nilainya. Selain field, desain juga mengenal anggota static var yang melekat pada tipe itu sendiri dan bukan pada instance tertentu.
// tidak-dijalankan
class Titik {
var x: i32;
var y: i32;
}Kerangka di atas belum dapat berdiri sendiri sebagai program, karena setiap program Carbon memerlukan baris package dan fungsi Main. Kelas yang sama dilengkapi metode dan dijalankan pada bagian berikutnya agar seluruh mekanismanya terlihat sekaligus. Penamaan kelas mengikuti gaya PascalCase sebagaimana terlihat pada Titik, sedangkan field ditulis dalam gaya camelCase.
Instansiasi dengan nilai struct#
Instance sebuah kelas dibuat dari nilai struct, yaitu nilai yang ditulis dengan tanda kurung kurawal dan nama field berawalan titik. Nilai {.x = 3, .y = 4} menyediakan isi untuk field x dan y, dan konversi implisit dari nilai struct ke tipe kelas terjadi pada saat pengikatan. Menurut desain, kelas nominal boleh mendefinisikan nilai awal field, sehingga nilai struct yang menyertakan sebagian field saja tetap sah. Setelah instance terbentuk, field-nya dapat dibaca dan ditimpa melalui akses titik sepanjang bindingnya dideklarasikan dengan var.
Program berikut merangkum seluruh mekanisme tersebut, mulai dari definisi kelas, pembuatan instance, hingga perubahan isi field.
package sample api;
class Titik {
var x: i32;
var y: i32;
fn Jumlah(self: Titik) -> i32 {
return self.x + self.y;
}
}
fn Main() -> i32 {
var t: Titik = {.x = 3, .y = 4};
Print("jumlah: {0}", Titik.Jumlah(t));
Print("x = {0}", t.x);
t.x = 10;
Print("x baru = {0}", t.x);
Print("jumlah baru: {0}", Titik.Jumlah(t));
return 0;
}jumlah: 7
x = 3
x baru = 10
jumlah baru: 14
result: 0Deklarasi var t: Titik = {.x = 3, .y = 4}; membuat instance dengan field x bernilai 3 dan y bernilai 4, sehingga metode Jumlah menghasilkan 7. Penugasan t.x = 10; menimpa satu field saja, dan panggilan Jumlah berikutnya menghasilkan 14 karena metode selalu membaca isi field terkini. Perubahan ini menunjukkan bahwa field milik instance yang dideklarasikan dengan var bersifat dapat diubah, sejajar dengan semantik var pada binding biasa.
Metode dan parameter self#
Metode adalah fungsi anggota yang parameter eksplisit pertamanya bernama self. Parameter tersebut mengikat objek yang menjadi sasaran pemanggilan. Dokumen desain mengizinkan tipe self untuk tidak ditulis karena secara bawaan mengikuti Self, yaitu tipe kelas yang sedang didefinisikan, tetapi interpreter saat ini masih menuntut tipe yang eksplisit, sehingga bentuk self: Titik digunakan sepanjang topik ini. Di dalam badan metode tidak ada akses anggota secara implisit, sehingga field selalu diakses melalui self.x dan self.y. Aturan ini membuat asal setiap nama terbaca tanpa perlu mencari konteks tambahan.
Dokumen desain memungkinkan dua bentuk pemanggilan metode, yaitu t.Jumlah() melalui objek dan Titik.Jumlah(t) melalui nama tipe dengan objek sebagai argumen pertama. Interpreter Explorer saat ini baru menerima bentuk kedua, sedangkan bentuk panggilan titik pada instance masih menghasilkan error. Program berikut memperlihatkan penolakan tersebut secara utuh.
package sample api;
class Titik {
var x: i32;
var y: i32;
fn Jumlah(self: Titik) -> i32 {
return self.x + self.y;
}
}
fn Main() -> i32 {
var t: Titik = {.x = 3, .y = 4};
Print("jumlah: {0}", t.Jumlah());
return 0;
}COMPILATION ERROR: <source>:14: wrong number of arguments in function call, expected 1 but got 0Pesan error tersebut menyatakan bahwa fungsi mengharapkan satu argumen, yaitu self, tetapi menerima nol. Pada bentuk panggilan titik, objek seharusnya terisi otomatis ke parameter self, dan mekanisme tersebut belum diterapkan interpreter. Perbaikan yang berjalan saat ini adalah memanggil melalui nama tipe, yaitu Titik.Jumlah(t), sebagaimana dilakukan pada program titik.carbon.
Enkapsulasi dalam desain#
Semua anggota kelas pada desain Carbon bersifat publik secara bawaan, dan pembatasan akses dilakukan dengan kata kunci private atau protected pada deklarasi yang ingin dibatasi. Keputusan ini mengikuti bahasa modern seperti Kotlin dan Python yang menilai bahwa kebanyakan pembaca lebih membutuhkan keterbacaan antarmuka publik. Kata kunci tersebut ditempelkan pada tiap deklarasi, bukan pada label yang berlaku untuk semua deklarasi berikutnya sebagaimana pada C++.
// tidak-dijalankan
class Dompet {
fn Saldo(self: Dompet) -> i32;
private var saldo: i32;
}Status kedua bentuk di atas pada interpreter perlu dinyatakan secara jujur. Deklarasi private masih ditolak tahap penguraian, sehingga enkapsulasi melalui kontrol akses belum dapat diuji di Explorer. Metode yang mengubah isi instance juga belum dapat diuji, karena bentuk parameter ref self yang ditetapkan desain untuk keperluan itu masih ditolak parser. Kelas yang dapat dijalankan saat ini adalah kelas dengan field publik dan metode yang hanya membaca self, sedangkan bagian desain lainnya menunggu implementasi interpreter.
Ringkasan#
- Kelas mendefinisikan tipe nominal dengan field yang dideklarasikan
vardi dalam badan kelas, dan field menentukan data setiap instance. - Instance dibuat dari nilai struct seperti
{.x = 3, .y = 4}, dan field instance yang terikat denganvardapat dibaca maupun ditimpa. - Metode adalah fungsi anggota dengan parameter
selfsebagai masukan pertama, dan interpreter saat ini menerima pemanggilan melalui nama tipe sepertiTitik.Jumlah(t). - Kontrol akses
privateserta metode mutator denganref selfmerupakan bagian desain yang belum diterima parser Explorer.
Referensi#
- Classes — Carbon Language — Dokumen desain kelas yang menetapkan field, nilai struct untuk instansiasi, metode dengan self, dan kontrol akses.
- Language design — Carbon Language — Ikhtisar desain yang memuat bagian kelas, metode, dan akses anggota dalam tur bahasa.
- Carbon Explorer — Compiler Explorer — Layanan daring tempat seluruh program yang dapat dijalankan pada topik ini diuji dengan kompiler Explorer (trunk).