Lingkup

Lingkup variabel lokal, konstanta, dan urutan pencarian metode (method lookup).

Daftar isi

Lingkup, atau scope dalam istilah pemrograman, menentukan wilayah program tempat sebuah nama dikenal dan dapat digunakan. Topik ini membahas lingkup variabel lokal di dalam metode, sifat konstanta, kerancuan ketika variabel dan metode menggunakan nama yang sama, serta urutan pencarian metode secara ringkas. Setelah membacanya, batas antara nama yang terlihat dan tidak terlihat pada setiap titik program dapat dijelaskan dengan pasti.

Lingkup metode terpisah#

Setiap metode memiliki lingkup variabel lokal sendiri, sehingga variabel lokal yang didefinisikan di luar metode tidak terlihat di dalam isinya. Pemisahan ini berlaku dua arah, yaitu variabel di dalam metode juga hilang setelah eksekusinya selesai. Untuk data yang berbentuk variabel lokal, satu-satunya jalan masuk ke dalam metode adalah parameter, dan satu-satunya jalan keluar adalah nilai kembalian. Diagram berikut menggambarkan batas tersebut, yaitu variabel diskon berada di lingkup tingkat atas sementara metode harga_akhir hanya melihat parameternya.

Lingkup tingkat atasdiskon = 10Lingkup metode harga_akhirhargadiskontidak terlihat dari siniData masuk ke metodehanya lewat parameter.Hasil keluar hanya lewatnilai kembalian.Variabel luar tidak terbaca.
Batas lingkup variabel lokal antara tingkat atas dan isi metode

Program berikut memperlihatkan keadaan itu terjadi secara nyata. Variabel diskon didefinisikan di tingkat atas, lalu metode harga_akhir mencoba membacanya dari dalam isinya.

ruby Berkas lingkup_lokal.rb
# tidak-dijalankan

diskon = 10

def harga_akhir(harga)
  harga - diskon
end

puts harga_akhir(200)
bash
# menjalankan berkas yang membaca variabel di luar lingkupnya
ruby lingkup_lokal.rb
text Keluaran
lingkup_lokal.rb:4:in 'Object#harga_akhir': undefined local variable or method 'diskon' for main (NameError)

  harga - diskon
          ^^^^^^
	from lingkup_lokal.rb:7:in '<main>'

Pesan error tersebut menyatakan bahwa nama diskon tidak dikenal pada saat metode harga_akhir dieksekusi, meskipun variabelnya jelas berada di bagian atas berkas. Perlakuan yang benar adalah mengirim nilainya lewat parameter, misalnya def harga_akhir(harga, diskon) lalu memanggil harga_akhir(200, 10). Dengan begitu metode tidak bergantung pada nama di luar lingkupnya dan dapat diuji dengan nilai apa pun.

Konstanta#

Konstanta didefinisikan dengan nama yang diawali huruf kapital dan, berbeda dari variabel lokal, tetap terlihat dari dalam metode yang didefinisikan pada tingkat yang sama. Sifat ini menjadikan konstanta tempat yang tepat untuk nilai yang digunakan bersama oleh banyak metode, misalnya tarif pajak atau faktor konversi yang tetap selama program berjalan.

ruby konstanta.rb
PAJAK = 0.11

def harga_akhir(harga)
  (harga * (1 + PAJAK)).round(2)
end

puts harga_akhir(10_000)
text Keluaran
11100.0

Metode harga_akhir membaca konstanta PAJAK tanpa perlu dikirim sebagai parameter, karena pencarian nama konstanta melibatkan lingkup tempat metode itu didefinisikan. Untuk nilai yang benar-benar tetap, konvensi umumnya menuliskan seluruh huruf dengan kapital dan garis bawah sebagai pemisah, sebagaimana PAJAK. Nilai konstanta memang dimaksudkan untuk tidak berubah, dan Ruby memberi peringatan apabila konstanta yang sama ditetapkan dua kali, meskipun program tetap berjalan. Peringatannya berupa pesan warning: already initialized constant di terminal dan tidak menghentikan eksekusi program. Untuk nilai yang berubah selama program dieksekusi, variabel yang dikirim lewat parameter tetap menjadi pilihan yang tepat.

Ketika nama bertabrakan#

Apabila sebuah variabel lokal dan metode menggunakan nama yang sama, Ruby memilih variabel lokal pada pemanggilan tanpa tanda kurung. Parser, yaitu bagian Ruby yang membaca kode sebelum eksekusi, menandai sebuah nama sebagai variabel lokal begitu penugasannya terlihat, bukan ketika penugasan itu dieksekusi. Sejak titik itu, nama yang sama dianggap variabel. Program berikut menunjukkan peralihannya secara bertahap.

ruby bayang_nama.rb
def nilai
  10
end

p nilai

nilai = 30

p nilai
p nilai()
text Keluaran
10
30
10

Pemanggilan pertama terjadi sebelum ada penugasan, sehingga nilai dibaca sebagai metode dan mencetak 10. Setelah nilai = 30 dieksekusi, nama yang sama menunjuk variabel lokal, sehingga p nilai mencetak 30. Tanda kurung kosong pada nilai() memaksa Ruby memanggil metode, dan hasilnya kembali berupa 10.

Kerancuan ini hanya terjadi pada pemanggilan tanpa penerima, karena bentuk objek.nilai selalu dibaca sebagai pemanggilan metode pada objek tersebut. Dokumentasi Ruby menyebut kasus ini sebagai kerancuan antara nama variabel dan nama metode, serta menyarankan tanda kurung kosong untuk memaksa pemanggilan metode. Tabrakan semacam ini mudah dihindari dengan memilih nama metode yang lebih spesifik, misalnya nilai_awal, sehingga tidak bersaing dengan variabel bernama nilai.

Urutan pencarian metode secara ringkas#

Ketika sebuah metode dipanggil, Ruby mencari definisinya mulai dari kelas tempat objek penerima berada, lalu naik menyusuri kelas di atasnya sampai definisinya ditemukan. Apabila penyusuran mencapai puncak rantai tanpa menemukan definisinya, Ruby memunculkan error NoMethodError. Urutan penyusuran ini disebut method lookup. Pada program tanpa definisi kelas, semua metode tingkat atas dilampirkan ke kelas Object, sehingga dapat dipanggil dari mana saja dalam skrip tanpa penerima.

ruby pemilik_metode.rb
def sapa
  "hai"
end

p method(:sapa).owner
text Keluaran
Object

Metode bawaan method mengambil objek metode untuk nama yang diberikan, dan owner menyatakan letak definisinya. Keluaran Object membuktikan pernyataan di atas, yaitu metode sapa yang didefinisikan di tingkat atas menjadi milik Object. Pembahasan di sini sengaja berhenti pada kasus tanpa kelas, karena rantai pencarian yang melibatkan pewarisan dan modul campuran (mixin) menyusul pada materi kelas. Untuk kasus sederhana saat ini, aturan yang perlu dipegang hanyalah satu, yaitu setiap pemanggilan tanpa penerima dicari mulai dari kelas tempat objek penerimanya berada.

Ringkasan#

  • Setiap metode memiliki lingkup variabel lokal sendiri, sehingga variabel dari luar tidak terlihat di dalam metode.
  • Data masuk ke metode lewat parameter dan keluar lewat nilai kembalian.
  • Konstanta yang didefinisikan di tingkat atas tetap terbaca dari dalam metode.
  • Pada nama yang sama, Ruby memilih variabel lokal ketika pemanggilan ditulis tanpa kurung, sedangkan tanda kurung kosong memaksa pemanggilan metode.
  • Metode tingkat atas menjadi milik kelas Object, dan pencarian metode menyusuri kelas objek penerima ke atas.

Referensi#