Metode instans

Metode instans, pemanggilan metode pada objek, dan peran self di dalam kelas.

Daftar isi

Metode instans adalah metode yang dipanggil pada sebuah objek dan mengoperasikan data milik objek tersebut. Topik ini membahas cara metode instans didefinisikan di dalam kelas dan dipanggil lewat tanda titik, peran self sebagai penerima implisit di dalam metode, pemanggilan metode lain dari sebuah metode, serta urutan pencarian metode secara ringkas. Setelah membacanya, alur dari pemanggilan metode hingga definisinya dapat dilacak dengan pasti.

Metode instans dan pemanggilan lewat titik#

Metode instans didefinisikan di dalam tubuh kelas dengan pasangan def dan end, sama seperti metode biasa, tetapi tubuhnya bekerja pada data milik objek penerima. Pemanggilannya dilakukan dengan menuliskan penerima, tanda titik, lalu nama metodenya, misalnya buku.deskripsi. Secara konseptual, pemanggilan tersebut adalah pengiriman pesan (message passing), yaitu objek penerima diminta menjalankan metode bernama tertentu, dan keputusan metode mana yang dijalankan ditentukan oleh penerimanya.

Program berikut mendefinisikan kelas Buku dengan dua metode instans, yaitu judul_lengkap yang menyusun teks dari dua variabel instans, dan deskripsi yang memanggil judul_lengkap dari dalam tubuhnya.

ruby buku.rb
# Metode instans pada kelas Buku beserta pemilik definisinya.
class Buku
  def initialize(judul, penulis)
    @judul = judul
    @penulis = penulis
  end

  def judul_lengkap
    "#{@judul} karya #{@penulis}"
  end

  def deskripsi
    "Buku \"#{judul_lengkap}\" tersedia di rak."
  end
end

buku = Buku.new("Sejarah Batik", "Citra")

p buku.deskripsi
p buku.method(:deskripsi).owner
p buku.method(:class).owner
text Keluaran
"Buku \"Sejarah Batik karya Citra\" tersedia di rak."
Buku
Kernel

Metode deskripsi menyisipkan hasil judul_lengkap ke dalam interpolasinya tanpa menyebut penerima apa pun, dan pola semacam ini menjadi cara baku memanggil metode lain dari sebuah metode. Dua baris terakhir menggunakan method(:nama) untuk mengambil objek metode dari nama yang diberikan, lalu owner melaporkan letak definisinya. Definisi deskripsi berada di Buku, sedangkan class tidak pernah didefinisikan di mana pun dalam program ini, karena metode tersebut diwarisi dari Kernel, salah satu leluhur hampir semua kelas Ruby.

Setiap pemanggilan metode pada objek terdiri atas tiga bagian, yaitu penerima, tanda titik, dan nama metode beserta argumennya. Nama metode boleh diakhiri tanda tanya jika metode itu menjawab benar atau salah, sesuai konvensi metode predicate yang sudah dikenal sebelumnya. Tanda kurung pada pemanggilan boleh ditulis maupun tidak, dan kode Ruby sehari-hari lazimnya melewatkan tanda kurung jika argumennya tidak ada atau mudah dibaca tanpanya.

self sebagai penerima implisit#

Di dalam tubuh metode instans, self merujuk pada objek yang sedang menerima pemanggilan. Pemanggilan tanpa penerima, seperti judul_lengkap di dalam deskripsi, sesungguhnya dikirim kepada self, sehingga tulisan lengkapnya adalah self.judul_lengkap. Karena itulah metode instans selalu bekerja pada data objek penerimanya, meskipun tidak ada satu pun nama objek yang disebut di dalam tubuhnya.

Bukti bahwa self adalah objek penerima dapat ditunjukkan dengan equal?, yaitu metode yang menguji apakah dua nama menunjuk objek yang sama. Program berikut membuat dua buku dengan isi sama persis, lalu membandingkan objek pertama dengan dirinya sendiri dan dengan objek kedua.

ruby Membuktikan self adalah objek penerima
class Buku
  def initialize(judul, penulis)
    @judul = judul
    @penulis = penulis
  end

  def milik_sendiri(objek)
    self.equal?(objek)
  end
end

a = Buku.new("Sejarah Batik", "Citra")
b = Buku.new("Sejarah Batik", "Citra")

p a.milik_sendiri(a)
p a.milik_sendiri(b)
text Keluaran
true
false

Ketika a.milik_sendiri(a) dijalankan, self di dalam metode tersebut adalah objek yang ditunjuk a, sehingga hasilnya true. Pada pemanggilan kedua, self tetap objek milik a, sedangkan b adalah objek lain dengan isi yang sama, sehingga hasilnya false. Perbedaan ini menegaskan bahwa kesamaan isi tidak membuat dua objek menyatu, dan self selalu mengikuti penerima pemanggilan.

Pemanggilan tanpa penerima hanya sah sebagai pemanggilan pada self di dalam metode instans, karena penerimanya memang jelas. Di luar metode, pemanggilan yang sama dikirim kepada objek tingkat atas yang berbeda, sehingga metode milik kelas tidak akan pernah ditemukan pada objek tersebut. Aturan ini menjelaskan mengapa judul_lengkap cukup ditulis begitu saja di dalam deskripsi, tanpa penerima dan tanpa awalan apa pun.

Pemilik definisi dan urutan pencarian#

Setiap pemanggilan metode menuntut Ruby mencari definisinya terlebih dahulu. Pencarian dimulai dari kelas milik objek penerima, lalu naik ke kelas induknya, dan seterusnya hingga definisi yang cocok ditemukan. Urutan penyusuran ini disebut method lookup, dan keluaran owner pada bagian sebelumnya memperlihatkan ujung rantainya, yaitu Buku untuk metode yang didefinisikan sendiri dan Kernel untuk metode warisan.

Dua instans dari kelas yang sama menemukan metodenya pada rantai yang sama, sehingga perilakunya identik meskipun datanya berbeda. Apabila tidak ada satu pun definisi yang cocok sampai akhir rantai, Ruby memunculkan NoMethodError, seperti yang sudah terlihat pada kasus metode yang belum didefinisikan. Rantai pencarian akan bertambah panjang ketika pewarisan digunakan, dan aturan yang perlu dipegang saat ini tetap satu, yaitu pencarian selalu berangkat dari kelas milik penerima.

Kesalahan umum#

Kesalahan yang sering luput dari perhatian pada metode instans terjadi ketika sebuah metode hendak mengubah atribut milik objeknya sendiri. Penugasan tanpa penerima dibaca Ruby sebagai pembuatan variabel lokal, bukan pemanggilan metode setter, sehingga variabel instansnya tidak pernah berubah dan tidak ada error yang muncul.

ruby penulis-lokal.rb
# Metode ganti_penulis yang keliru dan versi yang benar dengan self.
class Buku
  attr_accessor :penulis

  def initialize(penulis)
    @penulis = penulis
  end

  def ganti_penulis_salah(nama)
    penulis = nama
  end

  def ganti_penulis(nama)
    self.penulis = nama
  end
end

buku = Buku.new("Ali")

p buku.ganti_penulis_salah("Budi")
p buku.penulis

buku.ganti_penulis("Budi")
p buku.penulis
text Keluaran
"Budi"
"Ali"
"Budi"

Metode ganti_penulis_salah mengembalikan "Budi" karena nilai kembalian penugasan memang teks itu, tetapi p buku.penulis berikutnya tetap mencetak "Ali". Penugasan penulis = nama hanya membuat variabel lokal baru yang hilang ketika metodenya selesai dijalankan. Perbaikannya ada pada ganti_penulis, yaitu menyertakan penerima secara eksplisit dalam bentuk self.penulis = nama, sehingga Ruby memanggil metode penulis= milik objek dan @penulis benar-benar diperbarui.

Gejala semacam ini sulit dilacak karena tidak ada error yang muncul, dan program tampak berjalan normal dengan data yang tidak pernah berubah. Apabila sebuah atribut terasa tidak pernah terisi atau tidak pernah berubah, periksa apakah penugasannya di dalam metode menyertakan self. Kebiasaan menulis self.atribut = nilai sejak awal mencegah kesalahan ini sepenuhnya, sedangkan penugasan tanpa penerima hanya tepat untuk variabel lokal.

Ringkasan#

  • Metode instans didefinisikan di dalam tubuh kelas dan dipanggil pada objek dengan tanda titik sebagai pengiriman pesan.
  • Di dalam metode instans, self adalah objek penerima, dan pemanggilan tanpa penerima dikirim kepada self.
  • method(:nama).owner melaporkan letak definisi metode, sedangkan pencarian metode berangkat dari kelas milik penerima dan naik ke atas.
  • Perubahan atribut dari dalam metode wajib menulis self.atribut = nilai, karena tanpa penerima Ruby membuat variabel lokal.

Referensi#