Kelas memungkinkan data dan perilaku yang berhubungan dikemas menjadi satu cetak biru, kemudian diwujudkan menjadi banyak objek yang berdiri sendiri. Topik ini membahas kata kunci class, peran initialize sebagai konstruktor (constructor), variabel instans berawalan @, pembuatan objek dengan new, serta attr_accessor untuk menyediakan akses ke atribut dari luar. Setelah membacanya, kelas sederhana untuk menyimpan data siswa dapat didefinisikan dan digunakan secara utuh.
Mendefinisikan kelas#
Kelas didefinisikan dengan kata kunci class, diikuti nama kelasnya, lalu tubuh kelas hingga end. Nama kelas diawali huruf kapital dan ditulis dalam gaya CamelCase, misalnya Siswa, karena nama kelas diperlakukan sebagai konstanta. Tubuh kelas memuat metode yang dimiliki setiap objek yang lahir darinya, dan kelompok metode inilah yang menentukan perilaku objek-objek tersebut. Objek yang dihasilkan dari sebuah kelas disebut instans, sedangkan proses pembuatannya disebut instansiasi.
Program berikut mendefinisikan kelas Siswa dengan dua data, yaitu nama dan nilai, beserta satu metode bernama status yang menilai kelulusan dari data tersebut.
# Kelas Siswa dengan initialize dan variabel instans.
class Siswa
def initialize(nama, nilai)
@nama = nama
@nilai = nilai
end
def status
if @nilai >= 75
"lulus"
else
"remedial"
end
end
end
citra = Siswa.new("Citra", 88)
budi = Siswa.new("Budi", 70)
p citra.status
p budi.status"lulus"
"remedial"Metode initialize dijalankan secara otomatis setiap kali Siswa.new dipanggil, dan argumen yang diberikan pada new diteruskan ke metode tersebut. Dua baris penugasan di dalamnya mengisi @nama dan @nilai, yaitu variabel instans (instance variable) berawalan @ yang melekat pada satu objek tertentu. Metode status membaca @nilai milik objek yang sedang memanggilnya, sehingga Citra dinyatakan lulus sedangkan Budi masuk remedial sesuai nilai masing-masing.
Definisi kelas dibaca sekali ketika berkas dieksekusi, dan pasangan class dengan end menutup tubuhnya. Metode di dalam tubuh kelas baru berjalan ketika instans memanggilnya, sehingga urutan mendefinisikannya bebas. Selama pengerjaan latihan, satu berkas boleh memuat satu kelas, sedangkan proyek yang semakin besar lazimnya memisahkan setiap kelas ke berkasnya sendiri.
Variabel instans milik masing-masing objek#
Variabel instans menjadi tempat objek menyimpan keadaannya, dan setiap objek memegang salinannya sendiri yang terpisah dari objek lain. Kelas Siswa hanya ditulis sekali, tetapi Siswa.new dapat dipanggil berkali-kali untuk menghasilkan banyak siswa dengan data berbeda. Mengubah @nilai milik satu siswa tidak pernah memengaruhi siswa lainnya, karena masing-masing menyimpan nilainya pada objeknya sendiri.
Penamaan variabel instans mengikuti gaya snake_case dan biasanya disamakan dengan makna datanya, misalnya @nama untuk nama dan @nilai untuk nilai ujian. Tidak ada deklarasi tipe sebelumnya, karena variabel instans lahir pada penugasan pertama dan dapat menyimpan objek apa pun. Apabila sebuah metode membaca variabel instans yang belum pernah ditugaskan, hasilnya nil tanpa memunculkan error, sehingga variabel tersebut dapat diperiksa dengan nil? jika diperlukan.
Dua instans yang dibuat dengan argumen sama tetap merupakan dua objek yang berbeda, karena keunikannya terletak pada identitas objeknya dan bukan pada isinya. Inilah sebabnya perubahan pada satu instans tidak pernah bocor ke instans lain yang bernilai sama. Pemahaman ini berguna sebelum atribut dibuka lewat attr_accessor, karena pembacaan dan penulisan lewat metode tetap menyasar variabel instans milik satu objek tersebut.
attr_accessor#
Variabel instans tidak dapat dibaca dari luar objek secara langsung, karena Ruby tidak menyediakan jalur menuju @nama selain lewat metode. Program berikut memanggil citra.nama padahal kelasnya belum mendefinisikan metode nama, lalu error yang muncul ditangkap dan dicetak.
class Siswa
def initialize(nama, nilai)
@nama = nama
@nilai = nilai
end
end
citra = Siswa.new("Citra", 88)
begin
citra.nama
rescue NoMethodError => e
puts e.class
puts e.message
endNoMethodError
undefined method 'nama' for an instance of SiswaSolusi yang idiomatis adalah attr_accessor, yaitu satu baris deklarasi yang mendefinisikan metode baca dan metode tulis untuk setiap symbol yang diberikan. Deklarasi attr_accessor :nama, :nilai menghasilkan nama dan nilai untuk membaca, serta nama= dan nilai= untuk mengubah variabel instans dengan nama yang sama. Dengan metode-metode tersebut, data siswa dapat dibaca dan diperbarui dari luar objek.
# Kelas Siswa dengan attr_accessor untuk nama dan nilai.
class Siswa
attr_accessor :nama, :nilai
def initialize(nama, nilai)
@nama = nama
@nilai = nilai
end
def status
if @nilai >= 75
"lulus"
else
"remedial"
end
end
end
citra = Siswa.new("Citra", 88)
puts citra.nama
puts citra.nilai
citra.nilai = 95
puts citra.nilai
puts citra.statusCitra
88
95
lulusBaris citra.nilai = 95 sesungguhnya memanggil metode nilai= dengan argumen 95, sehingga @nilai diperbarui dan status langsung menilai ulang hasilnya. Metode status tetap ditulis sebagai metode biasa karena nilainya dihitung dari data, bukan disimpan sebagai atribut. Deklarasi attr_accessor digunakan untuk atribut data yang memang layak dibaca dan diubah dari luar.
Setiap symbol pada attr_accessor menghasilkan sepasang metode, dan beberapa symbol boleh ditulis dalam satu baris atau dipisah per baris sesuai kerapian. Metode yang dihasilkannya adalah metode biasa, sehingga kelak dapat ditimpa oleh versi manual jika aksesnya perlu diberi logika. Karena dibuat sebagai metode publik, atribut semacam ini menjadi bagian dari antarmuka kelas yang dapat dipanggil dari luar.
Kesalahan umum#
Kesalahan yang lazim saat kelas baru ditulis adalah memanggil new tanpa argumen yang cukup. Karena initialize mendeklarasikan dua parameter, panggilan tanpa argumen langsung ditolak sebelum objek selesai dibuat.
class Siswa
def initialize(nama, nilai)
@nama = nama
@nilai = nilai
end
end
begin
Siswa.new
rescue ArgumentError => e
puts e.class
puts e.message
endArgumentError
wrong number of arguments (given 0, expected 2)Pesan wrong number of arguments menyebut jumlah argumen yang diberikan dan yang diharapkan, sehingga pemanggilannya tinggal disesuaikan. Kesalahan lain yang mirip adalah memanggil metode instans pada kelasnya, misalnya Siswa.status, yang memunculkan NoMethodError karena status milik instans dan bukan milik kelas. Pembedanya sederhana, yaitu data tersimpan pada instans, sedangkan kelas hanya menyimpan definisi metodenya. Kedua error semacam ini mudah dilacak karena pesannya menyebut penerima, nama metode, atau jumlah argumen yang bermasalah.
Kesalahan ketiga yang senada adalah lupa menulis @ di depan nama variabel instans. Tanpa @, baris penugasan di dalam metode hanya membuat variabel lokal, sehingga data tidak tersimpan pada objek dan pembacaan atributnya menghasilkan nil. Tidak ada error yang muncul pada saat penugasannya, sehingga setiap baris di dalam initialize perlu diperiksa kembali jika atribut terasa tidak pernah terisi.
Ringkasan#
- Kelas didefinisikan dengan
classhinggaend, dan namanya ditulis gaya CamelCase karena berperan sebagai konstanta. initializedijalankan otomatis olehnew, dan argumen padanewditeruskan keinitialize.- Variabel instans berawalan
@melekat pada tiap objek, tidak saling memengaruhi antarinstans, dan bernilainilsebelum ditugaskan. attr_accessor :xmenghasilkan metodexdanx=untuk membaca serta mengubah@xdari luar objek.
Referensi#
- Class — Dokumentasi Ruby 3.4
— Dokumentasi kelas Class, termasuk peran
newdalam membuat instans baru. - Module#attr_accessor — Dokumentasi Ruby 3.4 — Definisi resmi attr_accessor beserta metode baca dan tulis yang dihasilkannya.