Bagikan melalui


Masa Pakai Objek: Bagaimana Objek Dibuat dan Dihancurkan (Visual Basic)

Instans kelas, objek, dibuat dengan menggunakan kata kunci New. Tugas inisialisasi sering kali harus dilakukan pada objek baru sebelum digunakan. Tugas inisialisasi umum termasuk membuka file, menyambungkan ke database, dan membaca nilai kunci registri. Visual Basic mengontrol inisialisasi objek baru menggunakan prosedur yang disebut konstruktor (metode khusus yang memungkinkan kontrol pada inisialisasi).

Setelah objek meninggalkan cakupan, objek dirilis oleh runtime bahasa umum (CLR). Visual Basic mengontrol rilis sumber daya sistem menggunakan prosedur yang disebut destruktor. Bersama-sama, konstruktor dan destruktor mendukung pembuatan pustaka kelas yang kuat dan dapat diprediksi.

Menggunakan Konstruktor dan Destruktor

Konstruktor dan destruktor mengontrol pembuatan dan penghancuran objek. Prosedur Sub New dan Sub Finalize dalam Visual Basic menginisialisasi dan menghancurkan objek; mereka menggantikan metode Class_Initialize dan Class_Terminate yang digunakan dalam Visual Basic 6.0 dan versi yang lebih lama.

Sub Baru

Konstruktor Sub New hanya dapat berjalan sekali ketika kelas dibuat. Konstruktor tersebut tidak dapat dipanggil secara eksplisit dari mana saja selain di baris kode pertama konstruktor lain baik di kelas yang sama atau kelas turunan. Selain itu, kode dalam metode Sub New selalu berjalan sebelum kode lain di kelas. Visual Basic secara implisit membuat konstruktor Sub New pada durasi jika Anda tidak secara eksplisit menentukan prosedur Sub New untuk kelas.

Untuk membuat konstruktor untuk kelas, buat prosedur bernama Sub New di mana saja dalam penentuan kelas. Untuk membuat konstruktor berparameter, tentukan nama dan jenis data argumen menjadi Sub New sama seperti Anda akan menentukan argumen untuk prosedur lain, seperti dalam kode berikut:

Sub New(ByVal s As String)

Konstruktor sering kelebihan beban, seperti dalam kode berikut:

Sub New(ByVal s As String, i As Integer)

Ketika Anda menentukan kelas yang berasal dari kelas lain, baris pertama konstruktor harus berupa panggilan ke konstruktor kelas dasar, kecuali kelas dasar memiliki konstruktor yang dapat diakses yang tidak memerlukan parameter. Panggilan ke kelas dasar yang berisi konstruktor di atas, misalnya, adalah MyBase.New(s). Jika tidak, MyBase.New bersifat opsional, dan runtime Visual Basic memanggilnya secara implisit.

Setelah Anda menulis kode untuk memanggil konstruktor objek induk, Anda dapat menambahkan kode inisialisasi tambahan ke prosedur Sub New. Sub New dapat menerima argumen ketika dipanggil sebagai konstruktor berparameter. Parameter ini diteruskan dari prosedur yang memanggil konstruktor, misalnya, Dim AnObject As New ThisClass(X).

Sub-Finalisasi

Sebelum merilis objek, CLR secara otomatis memanggil metode Finalize untuk objek yang menentukan prosedur Sub Finalize. Metode Finalize ini dapat berisi kode yang perlu dijalankan tepat sebelum objek dihancurkan, seperti kode untuk menutup file dan menyimpan informasi status. Ada sedikit penalti performa untuk mengeksekusi Sub Finalize, jadi Anda harus menentukan metode Sub Finalize hanya ketika Anda perlu merilis objek secara eksplisit.

Catatan

Pengumpul sampah di CLR tidak (dan tidak dapat) membuang objek yang tidak dikelola, objek yang dijalankan sistem operasi secara langsung, di luar lingkungan CLR. Ini karena objek yang tidak dikelola yang berbeda harus dibuang dengan cara yang berbeda. Informasi tersebut tidak terkait langsung dengan objek yang tidak dikelola; informasi tersebut harus ditemukan dalam dokumentasi untuk objek. Kelas yang menggunakan objek yang tidak dikelola harus membuangnya dalam metode Finalize.

Destruktor Finalize adalah metode terlindungi yang hanya dapat dipanggil dari kelas miliknya, atau dari kelas turunan. Sistem memanggil Finalize secara otomatis ketika objek dihancurkan, jadi Anda tidak boleh secara eksplisit memanggil Finalize dari luar implementasi Finalize kelas turunan.

Tidak seperti Class_Terminate, yang dijalankan segera setelah objek tidak diatur ke apapun, biasanya ada penundaan antara ketika objek kehilangan cakupan dan ketika Visual Basic memanggil destruktor Finalize. Visual Basic .NET memungkinkan jenis destruktor kedua, IDisposable.Dispose, yang dapat secara eksplisit dipanggil kapan saja untuk segera merilis sumber daya.

Catatan

Destruktor Finalize tidak boleh melemparkan pengecualian, karena tidak dapat ditangani oleh aplikasi dan dapat menyebabkan aplikasi dihentikan.

Cara Kerja Metode Baru dan Finalisasi dalam Hierarki Kelas

Setiap kali instans kelas dibuat, runtime bahasa umum (CLR) mencoba menjalankan prosedur bernama New, jika ada di objek tersebut. New adalah jenis prosedur yang disebut constructor yang digunakan untuk menginisialisasi objek baru sebelum kode lain dalam objek dijalankan. Konstruktor New dapat digunakan untuk membuka file, menyambungkan ke database, menginisialisasi variabel, dan mengurus tugas lain yang perlu dilakukan sebelum objek dapat digunakan.

Ketika instans kelas turunan dibuat, konstruktor Sub New kelas dasar dijalankan terlebih dahulu, diikuti dengan konstruktor di kelas turunan. Ini terjadi karena baris pertama kode dalam konstruktor Sub Newmenggunakan sintaks MyBase.New()untuk memanggil konstruktor kelas tepat di atas dirinya sendiri dalam hierarki kelas. Konstruktor Sub New kemudian dipanggil untuk setiap kelas dalam hierarki kelas sampai konstruktor untuk kelas dasar tercapai. Pada saat itu, kode dalam konstruktor untuk kelas dasar dijalankan, diikuti oleh kode di setiap konstruktor di semua kelas turunan dan kode di kelas yang paling diturunkan dijalankan terakhir.

Screenshot showing class hierarchy constructors and inheritance.

Ketika objek tidak lagi diperlukan, CLR memanggil metodeFinalize untuk objek tersebut sebelum membebaskan memorinya. Metode Finalize ini disebut destructor karena melakukan tugas pembersihan, seperti menyimpan informasi status, menutup file dan koneksi ke database, dan tugas lain yang harus dilakukan sebelum merilis objek.

Screenshot showing the Finalize method destructor.

Antarmuka IDisposable

Instans kelas sering mengontrol sumber daya yang tidak dikelola oleh CLR, seperti handel Windows dan koneksi database. Sumber daya ini harus dibuang dalam metode Finalize kelas, sehingga mereka akan dilepaskan ketika objek dihancurkan oleh pengumpul sampah. Namun, pengumpul sampah menghancurkan objek hanya ketika CLR membutuhkan lebih banyak memori bebas. Ini berarti bahwa sumber daya bisa tidak dirilis hingga lama setelah objek keluar dari cakupan.

Untuk melengkapi pengumpulan sampah, kelas Anda dapat menyediakan mekanisme untuk mengelola sumber daya sistem secara aktif jika mereka mengimplementasikan antarmuka IDisposable. IDisposable memiliki satu metode, Dispose, yang harus dipanggil klien ketika mereka selesai menggunakan objek. Anda dapat menggunakan metode Dispose untuk segera merilis sumber daya dan melakukan tugas seperti menutup file dan koneksi database. Tidak seperti destruktor Finalize, metode Dispose tidak dipanggil secara otomatis. Klien kelas harus secara eksplisit memanggil Dispose ketika Anda ingin segera merilis sumber daya.

Menerapkan IDisposable

Kelas yang mengimplementasikan antarmuka IDisposable harus menyertakan bagian kode ini:

  • Bidang untuk melacak apakah objek telah dibuang:

    Protected disposed As Boolean = False
    
  • Kelebihan beban Dispose yang membebaskan sumber daya kelas. Metode ini harus dipanggil dengan metode Dispose dan Finalize kelas dasar:

    Protected Overridable Sub Dispose(ByVal disposing As Boolean)
        If Not Me.disposed Then
            If disposing Then
                ' Insert code to free managed resources.
            End If
            ' Insert code to free unmanaged resources.
        End If
        Me.disposed = True
    End Sub
    
  • Implementasi Dispose yang hanya berisi kode berikut:

    Public Sub Dispose() Implements IDisposable.Dispose
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub
    
  • Pengambil-alihan metode Finalize yang hanya berisi kode berikut:

    Protected Overrides Sub Finalize()
        Dispose(False)
        MyBase.Finalize()
    End Sub
    

Berasal dari Kelas yang Mengimplementasikan IDisposable

Kelas yang berasal dari kelas dasar yang mengimplementasikan antarmuka IDisposable tidak perlu mengambil alih salah satu metode dasar kecuali menggunakan sumber daya tambahan yang perlu dibuang. Dalam situasi itu, kelas turunan harus mengambil alih metode Dispose(disposing) kelas dasar untuk membuang sumber daya kelas turunan. Pengambil-alihan ini harus memanggil metode Dispose(disposing) kelas dasar.

Protected Overrides Sub Dispose(ByVal disposing As Boolean)
    If Not Me.disposed Then
        If disposing Then
            ' Insert code to free managed resources.
        End If
        ' Insert code to free unmanaged resources.
    End If
    MyBase.Dispose(disposing)
End Sub

Kelas turunan tidak boleh mengambil alih metode Dispose dan Finalize kelas dasar. Ketika metode tersebut dipanggil dari instans kelas turunan, implementasi kelas dasar dari metode tersebut memanggil pengambil-alihan kelas turunan metode Dispose(disposing).

Pengumpulan Sampah dan Destruktor Finalisasi

.NET Framework menggunakan sistem pengumpulan sampah pelacakan referensi untuk merilis sumber daya yang tidak digunakan secara berkala. Visual Basic 6.0 dan versi yang lebih lama menggunakan sistem lain yang disebut penghitungan referensi untuk mengelola sumber daya. Meskipun kedua sistem melakukan fungsi yang sama secara otomatis, ada beberapa perbedaan penting.

CLR secara berkala menghancurkan objek ketika sistem menentukan bahwa objek tersebut tidak lagi diperlukan. Objek dirilis lebih cepat ketika sumber daya sistem berada dalam pasokan pendek, dan lebih jarang sebaliknya. Penundaan antara ketika objek kehilangan cakupan dan ketika CLR melepaskannya berarti bahwa, tidak seperti objek di Visual Basic 6.0 dan versi yang lebih lama, Anda tidak dapat menentukan dengan tepat kapan objek akan dihancurkan. Dalam situasi seperti itu, objek dikatakan memiliki masa pakai non-deterministik. Dalam kebanyakan kasus, masa pakai non-deterministik tidak mengubah cara Anda menulis aplikasi, selama Anda ingat bahwa destruktor Finalize bisa tidak segera dijalankan ketika objek kehilangan cakupan.

Perbedaan lain antara sistem pengumpulan sampah melibatkan penggunaan Nothing. Untuk memanfaatkan penghitungan referensi dalam Visual Basic 6.0 dan versi yang lebih lama, programmer terkadang menetapkan Nothing ke variabel objek untuk merilis referensi yang dimiliki variabel tersebut. Jika variabel memegang referensi terakhir ke objek, sumber daya objek segera dirilis. Dalam versi Visual Basic yang lebih baru, meskipun mungkin ada kasus di mana prosedur ini masih berharga, menjalankannya tidak pernah menyebabkan objek yang dirujuk segera merilis sumber dayanya. Untuk segera merilis sumber daya, gunakan metode Dispose objek, jika tersedia. Satu-satunya waktu Anda harus mengatur variabel ke Nothing adalah ketika masa pakainya lama relatif terhadap waktu yang diperlukan pengumpul sampah untuk mendeteksi objek yatim piatu.

Lihat juga