Lingkup dan Modul

Lingkup variabel, kode level modul dengan Module, dan pengelompokan namespace.

Daftar isi

Lingkup (scope) adalah wilayah kode yang dapat merujuk suatu elemen tanpa kualifikasi nama, dan VB.NET menyusunnya berjenjang dari blok, prosedur, modul, sampai namespace. Variabel yang dideklarasikan di dalam lingkup sempit tidak terlihat dari luar, sedangkan variabel yang dideklarasikan di lingkup luas terlihat oleh kode di dalamnya. Topik ini membahas tiga tingkat lingkup yang paling sering digunakan, peran Module sebagai wadah anggota yang dapat diakses tanpa objek, kata kunci Shared secara ringkas, serta pengelompokan kode dengan Namespace dan Imports.

Tiga tingkat lingkup#

Tingkat pertama adalah lingkup blok, yaitu wilayah di antara pasangan pernyataan seperti For...Next atau If...End If. Variabel yang dideklarasikan pada kepala blok hanya hidup di dalam blok itu, sehingga For i As Integer = 1 To 3 membuat i tidak dapat dirujuk lagi setelah Next. Tingkat kedua adalah lingkup prosedur, yaitu seluruh badan satu Sub atau Function, yang menampung parameternya beserta variabel Dim di dalamnya. Tingkat ketiga adalah lingkup modul, yaitu wilayah variabel yang dideklarasikan langsung di badan Module di luar prosedur mana pun, dan variabel semacam ini terlihat oleh semua prosedur di modul tersebut.

Diagram berikut menumpuk keempat wilayah itu, yaitu blok, prosedur, modul, dan namespace, dengan namespace sebagai pembungkus paling luar. Semakin ke dalam, semakin sempit wilayah rujukannya.

Tingkatan lingkup dari namespace sampai blokLingkup dari yang paling luas ke yang paling sempitNamespace SatuanModule KonversiFunction KeJamBlok For...Nextvariabel i hanya hidup di dalam blokpaling luasdiakses tanpa objekparameter dan variabel lokalpaling sempit
Tingkatan lingkup dari namespace sampai blok

Pemilihan lingkup mengikuti kebutuhan data. Nilai yang hanya digunakan pada satu perhitungan cukup menjadi variabel lokal, sedangkan data yang diakses bersama oleh beberapa prosedur di satu berkas layak menjadi variabel level modul. Mempersempit lingkup sebisa mungkin mempermudah penelusuran, karena daftar kandidat penyebab suatu nilai berubah ikut menyempit.

Program dengan tiga lingkup#

Program berikut menggunakan ketiga tingkat lingkup sekaligus, yaitu i di blok For, nilai di prosedur TambahSkor, dan totalSkor di level modul. Jalankan dengan dotnet run dan perhatikan bahwa akumulator totalSkor tidak dikirim sebagai parameter ke mana pun, tetapi isinya tetap naik.

vb LingkupNilai.vb
Module Program
    Private totalSkor As Integer = 0

    Sub TambahSkor(nilai As Integer)
        totalSkor += nilai
    End Sub

    Sub CetakTotal()
        Console.WriteLine($"Total skor: {totalSkor}")
    End Sub

    Sub Main()
        For i As Integer = 1 To 3
            TambahSkor(i * 10)
        Next
        CetakTotal()
    End Sub
End Module
text Keluaran
Total skor: 60

Prosedur Main memanggil TambahSkor tiga kali dengan nilai 10, 20, dan 30, sehingga totalnya 60. Variabel totalSkor berada di level modul, sehingga baik TambahSkor maupun CetakTotal membaca dan mengubahnya tanpa melalui parameter. Usia hidup variabel level modul menempel pada usia hidup program, sedangkan isi variabel lokal terbentuk ulang setiap prosedur dipanggil.

Bandingkan perilaku itu dengan variabel lokal. Apabila akumulator totalSkor dipindahkan ke dalam Main, prosedur TambahSkor tidak akan mengenalinya, dan setiap prosedur memerlukan parameternya sendiri untuk mengakses nilai yang sama. Deklarasi level modul menghilangkan pengiriman itu, tetapi konsekuensinya nilai itu dapat diubah oleh prosedur mana pun di modul, sehingga namanya harus jelas dan perubahannya mudah dilacak.

Module tanpa objek#

Module adalah wadah kode yang anggotanya dapat diakses langsung tanpa membuat objek. Tidak ada perintah New untuk sebuah modul, karena setiap modul memiliki tepat satu keberadaan sepanjang program berjalan. Anggota modul, baik variabel, prosedur, maupun konstanta, bersifat implisit Shared, yaitu melekat pada tipe dan bukan pada objek tertentu.

Kata kunci Shared sendiri lebih sering digunakan di dalam Class. Anggota kelas yang diberi Shared dapat dipanggil melalui nama kelasnya tanpa membuat objek, misalnya Math.Sqrt(9) pada pustaka standar yang anggotanya berlaku bersama untuk seluruh program. Dengan kata lain, Module dapat dibayangkan sebagai kelas yang seluruh anggotanya sudah Shared tanpa perlu menuliskannya satu per satu.

Tingkat akses bawaannya juga perlu diketahui. Modul bawaannya Friend, sehingga terlihat di seluruh proyek yang memuatnya, sedangkan anggotanya bawaan Public dan mengikuti jangkauan modulnya. Untuk kode bersama di satu aplikasi console kecil, nilai bawaan itu sudah memadai, dan penyesuaian akses baru diperlukan ketika kode mulai digunakan lintas proyek.

Namespace dan Imports#

Namespace mengelompokkan tipe-tipe yang berkaitan di bawah satu nama, misalnya Satuan untuk modul konversi satuan. Pustaka standar .NET juga tersusun demikian, dan Console sebenarnya adalah System.Console yang berasal dari namespace System. Nama lengkap dengan namespace selalu sah, tetapi pernyataan Imports di kepala berkas memungkinkan penulisan yang lebih pendek tanpa kualifikasi.

Program berikut terdiri atas dua berkas yang dikompilasi bersama, yaitu ModulUtama.vb sebagai titik masuk dan ModulBantu.vb yang memuat namespace beserta modul konversinya. Salin keduanya ke satu folder proyek console, lalu jalankan dengan dotnet run.

vb ModulUtama.vb
Imports Satuan

Module Program
    Sub Main()
        ' dengan Imports, nama modul cukup ditulis langsung
        Console.WriteLine($"3 km = {Konversi.KeMeter(3)} m")
        ' tanpa Imports, nama namespace disebut penuh
        Console.WriteLine($"120 menit = {Satuan.Konversi.KeJam(120)} jam")
    End Sub
End Module
vb ModulBantu.vb
Namespace Satuan
    Module Konversi
        Function KeMeter(kilometer As Integer) As Integer
            Return kilometer * 1000
        End Function

        Function KeJam(menit As Integer) As Integer
            Return menit \ 60
        End Function
    End Module
End Namespace
text Keluaran
3 km = 3000 m
120 menit = 2 jam

Kedua bentuk pemanggilan terlihat bersebelahan pada program di atas. Baris pertama memanggil Konversi.KeMeter(3) karena Imports Satuan sudah dituliskan di kepala berkas, sedangkan baris kedua memanggil Satuan.Konversi.KeJam(120) dengan nama penuhnya dan tetap sah kapan pun. Proyek console VB.NET dari SDK modern sudah mengimpor namespace yang lazim seperti System, dan itulah sebabnya Console.WriteLine cukup ditulis tanpa kualifikasi sejak topik program pertama. Pemilihan nama namespace mengikuti pola pustaka .NET, yaitu dimulai dari nama yang luas lalu menyempit ke arah isinya.

Kesalahan umum#

Kesalahan pertama adalah merujuk variabel blok dari luar bloknya. Kode yang menggunakan i sesudah Next ditolak compiler dengan pesan nama tidak dideklarasikan, karena usia i habis bersama bloknya. Perbaikannya dengan mendeklarasikan variabel hasil sebelum blok, lalu mengisinya di dalam blok.

Kesalahan kedua adalah mencoba membuat objek dari modul, misalnya New Konversi(). Compiler menolaknya karena modul tidak pernah diinstansiasi dan anggotanya sudah dapat dipanggil langsung. Pemanggilan panjang seperti Satuan.Konversi.KeJam(120) bukan tanda modul diinstansiasi, melainkan kualifikasi namespace yang sah. Apabila kebutuhannya benar-benar objek dengan keadaan sendiri, wadah yang tepat adalah Class, yang anggotanya biasanya memerlukan objek sebelum dipanggil.

Kesalahan ketiga adalah benturan nama ketika dua namespace memuat tipe senama. Penulisan singkat menjadi mengambang, dan compiler meminta nama penuh untuk membedakannya. Sertakan nama namespace pada pemanggilan yang bentrok, atau beri alias melalui bentuk Imports Alias = Namespace agar penulisannya tetap pendek. Periksa pula daftar Imports di kepala berkas, karena namespace yang tidak digunakan membuat daftarnya lebih ramai daripada kebutuhan sebenarnya.

Ringkasan#

  • Lingkup tersusun dari blok yang paling sempit, prosedur yang menampung parameter dan variabel lokalnya, sampai level modul yang terlihat oleh seluruh prosedur di modul tersebut dan hidup sepanjang program.
  • Module adalah wadah anggota yang diakses tanpa objek karena seluruh anggotanya implisit Shared, dengan modul bawaan Friend dan anggota bawaan Public.
  • Namespace mengelompokkan tipe yang berkaitan, dan Imports di kepala berkas mempersingkat rujukan, sedangkan nama penuh dengan namespace selalu sah.

Referensi#