Object Oriented Programming Pada Delphi - Bag 6

Pada artikel sebelumnya, kita sudah sedikit mengimplementasikan prinsip-prinsip OOP pada kelas TMruList. Pada artikel berikut ini, kita akan membahas beberapa hal prinsip tentang OOP lebih lanjut. Kita akan membahas skope variable dan method, constructor dan destructor, dll.



Skope Variable dan Method
Ketika kita bicara tentang skope dari variable dan method, artinya kita membicarakan dari mana suatu method/variable bisa diakses. Bisa juga kita artikan siapa saja yang bisa mengakses variable dan method tersebut . Pada kelas yang sudah kita buat, semua method dan variable bisa diakses oleh siapapun dan dari manapun. Hal yang demikian bukanlah design yang bagus. Coba perhatikan variable FNumItems pada kelas TMRUList.Variable ini hanya dipakai di dalam kelas tersebut untuk mencatat berapa jumlah string yang ada pada list. Karena variable ini kelihatan (bisa dipakai) oleh pengguna kelas , maka bisa saja si user mengganti nilai variable ini, maka hal ini akan merusak integritas kelas kita ini.
Jadi, kita harus membedakan variable dan method yang bisa diakses oleh user (di luar kelas) dengan variable atau method yang hanya bisa diakses dari dalam kelas. Kita seharusnya hanya mengijinkan user untuk melihat variable dan method yang berhubungan dengan interface kelas, yaitu hal-hal pokok yang diperlukan untuk menggunakan kelas tersebut . Detail implementasi dari kelas sebaiknya disembunyikan dari user. Dengan demikian kita bisa merubah detail dari implementasi kelas ini tanpa mengganggu baris kode user yang menggunakan kelas ini selama interface kelas tidak berubah. Hal ini merupakan prinsip OOP kedua, yaitu enkasulapsi (encsulaption).
Sidebar
Prinsip Enkasulapsi ….
Untuk menyembunyikan variable dan method dari pengguna kelas, si pembuat kelas bisa memisahkan kelasnya menjadi beberapa seksi (bagian). Seksi-seksi ini menentukan skope dari variable dan method yang dideklarasikan di masing-masing seksi tersebut. Sebuah kelas bisa mempunyai empat seksi, yaitu :

Public
Published
Private
Protected


Bagaimana skope dan siapa saja yang bisa mengakses variable/method kita tergantung di mana kita mendeklarasikan variable/method tersebut.

Public
Semua hal yang dideklarasikan pada bagian ini berarti bisa diakses oleh pengguna kelas. Kemudian, jika kita dalam mendeklarasikan method atau variable tidak dimasukkan ke seksi manapun, maka by default, method/variable tersebut seperti dideklarasikan di seksi public.

Private
Kebalikan dengan seksi public, semua yang dideklarasikan di seksi ini hanya bisa diakses dari kelas yang bersangkutan. Versi kedua dari kelas MRUList memberikan contoh variable yang dideklarasikan di seksi private, yaitu FNumItems dan FMList. Perhatikan baris kode berikut ini :
 
Type
 TMruList = Class
  Private
   FMList : Array[0..MRUMaxItems – 1] of String;
   FNumItems : Integer;
  Public
   Function Count : Integer;
   Procedure Add( s : String);
   Function GetString( n : Integer) : String
 End;

Dengan deklarasi seperti di atas, pengguna kelas ini tidak bisa langsung mengakses FMList atau FNumItems secara langsung. Hanya kelas MRUList sendiri yang bisa mengaksesnya. Jadi, pengguna kelas tidak perlu tahu apa itu FMList dan FNumItems . Hal inilah yang dimaksud enkasulapsi - yaitu menyembunyikan implementasi detail suatu kelas.

Protected
Seksi Protected , pada bagian ini, semua yang dideklarasikan bisa diakses dari kelas ini sendiri dan kelas-kelas turunannya. Pembahasan ini akan lebih detail nanti (kalau ada waktu) ketika membahas tentang inheritance.

Published
Seksi publised hampir sama dengan public. Bedanya, jika class ini berupa kelas komponen, maka semua yang dideklarasikan di seksi published ini akan muncul di object properties. Hal ini tidak terjadi jika dideklarasikan di seksi public.

Tibalah Saatnya Menuliskan Contructor & Destructor Sendiri

Dari artikel-artikel sebelumnya, kita sudah pernah membahas apa itu constructor– yaitu sebuah function khusus yang dipakai untuk mengalokasikan memori untuk objek dari kelas di mana constructor tersebut dideklarasikan. By default, suatu kelas mempunyai sebuah constructor yaitu create. Sebenarnya kita bisa mendeklarasikan constructor sendiri untuk kelas-kelas yang kita buat. Caranya sama dengan membuat sebuah method. Dengan membuat cosntructor sendiri, kita bisa memperloleh keuntungan yaitu kita bisa melakukan inisialisasi properti ketika constructor dipanggil.
Sebagai contoh, berikut ini saya tuliskan baris kode untuk mengalokasikan memori untuk objek bertipe kelas TSquare, setelah itu dilakukan inisialisi properti dari objek tersebut. :
 
o := TSquare.Create;
o.FX := 10;
o.FY := 10;
o.FWidth := 5;
o.FCaption := ‘First Square';

Jika kita menuliskan constructor sendiri untuk kelas TSquare ini, kita bisa mengirimkan nilai awal (initial value) dari atribut-atribut kelas TSQuare ini. Kita bisa menuliskan :
 
o := TSquare.Create( 10, 10, 5, ‘First Square'); 

Baris kode di atas lebih elegan dan menguntungkan. Dengan membuat constructor sendiri, kita bisa menjamin ada nilai awal untuk atribut dari kelas ketika pertama kali constructor dipanggil. Jika ada atribut yang tidak mempunyai nilai awal , lalu atribut-atribut tersebut dipakai pada suatu method, bisa jadi error yang akan ditampilkan oleh compiler. Lihat kode di bawah ini :
 
o := TSquare.Create; 
// Calculate its area; 
a := o.Area; 

Baris kode di atas, kita menjalankan method area (untuk menghitung luas) , tapi kita lupa melakukan inisialisasi atribut panjang dan lebar. Jika kita membuat contructor sendiri, kesalahan yang seperti ini akan bisa dihindari karena kita dipaksa untuk memasukkan nilai awal untuk atribut panjang dan lebar pada saat memanggil constructor.

Keuntungan lain dengan membuat constructor sendiri yaitu kita bisa melakukan inisialisasi suat objek yang dalam kelas. Dibagian awal dari artikel OOP Pada Delphi ini, kita membuat sebuah kelas yaitu TMRUList. Kelas ini mempunyai atribut yang bertipe TStringList. Sebelum bisa digunakan, atribut yang bertipe TStringList ini harus dialokasikan memori untuknya (Instansiasi, saya kebelakang akan menggunakan istilah instansiasi untuk menggantikan istilah "Mengalokasikan Memori"). Tempat yang paling tepat untuk meng-instantsiasi atribut ini adalah constructor. Jadi, ketika kelas TMRUList di-instantsiasi, pada saat yang sama kelas ini juga meng-instantsiasi atribut yang berti TStringList tersebut.

Sekarang, artibut yang bertipe TStringlist tadi juga perlu dibebaskan memori-nya (destroy, saya akan memakai istilah ini untuk menggantikan istilah "membebaskan memori") .Kapan yang tepat untuk men-destroy atribut tersebut? Saat yang yaitu ketika proses destryo objek yang bertipe TMRUList itu sendiri. Sama dengan proses instansiasi, proses destroy juga tidak otomatis dilakukan. Ketika objek TMRUList di-destroy, kita perle mengeksekusi baris kode yang akan men-destroy atribut yang bertipe TStringList. Di dalam delphi, disediakan method yang dipakai untuk men-destroy suatu object, yaitu destructor . Destructor bisa dibilang sebagai kebalikan dari constructor – destructor ini dipanggil ketia sebuah objek di-destroy.

Lebih jelasnya lihat baris kode berikut ini :
Kita deklarasikan sebuah constructor pada bagian deklarasi kelas dengan kata kunci Constructor :
 
Type
 TSquare = Class
 FX, FY : Integer;
 FCaption : String;
 FWidth : Integer;
 Function Area : Integer;
 
 Constructor Create( px, py : Integer; // deklarasi constructor
 pWidth : Integer; Caption : String;
End; 

Kemudian, kita tuliskan isi dari constructor tersebut pada bagian implementation. Pada bagian, kita juga menggunakan kata kunci Constructor:
 
Constructor TSquare.Create(px, py : Integer;
 pWidth : Integer; pCaption : String);
Begin
 Self.FX   := px;
 Self.FY   := py;
 Self.FWidth  := pWidth;
 Self.FCaption  := pCaption;
End;

Seperti yang terlihat pada baris kode di atas, , yang dilakukan constructor adalah meng-copy nilai dari parameter ke atribut yang ada pada kelas tersebut. Untuk kasus di atas, penggunaan keyword adalah optional saja. Hal ini karena nama parameter dengan atribut kelas berbeda. Jika anda menamakan paramer sama dengan atribut kelas, maka penggunaan keyword Self adalah sebuah keharusan. Namun, lebih baik anda menghindari penamaan yang sama antara paramer dan nama atribut kelas.

Baris kode berikut memperlihat constructor pada kelas TMRUList. Pada kelas ini, digunakan atribut yang bertipe TStringList , yaitu FMList , untuk menampung string yang paling akhir dipakai.
 
Constructor TMRUList.Create;
Begin
 FMList := TStringList.Create;
End;

Pada baris kode di atas, constructor hanya meng-instantsiasi kelas TStringList dan menyimpannya pada atribut FMList. Seperti yang sudah saya utarakan di atas, atribut FMList harus di-destroy ketika kelas TMRList ini di-destry. Kita harus lakukan hal ini di dalam destructor.

Delphi secara otomatis akan memanggil destructor ketika methog destroy dari suatu objek dijalankan.
 
mruList := TMRUList.Create;
Try
 // Work with mruList here
Finally
 mruList.Free; // baris ini akan memanggil destructor
End; 

Ketika method Free dijalankan, Delphi secara otomatis akan memanggil destructor. Destructor di deklarasikan dengan kata kunci Destructor. Yang perlu diingat, kita harus menambah kata kunci Override di belakang deklarasi destructor. Berikut deklarasi kelas TMRUList secara lengkap :
 
Type
 TMruList = Class
 Private
  FMList : TStringList;
  Constructor Create;
  Destructor Destroy; Override;
 Public
  Function Count : Integer;
  Procedure Add( s : String);
 Function GetString( n : Integer) : String
End;

Implemenasi dari destructor hampir sama dengan constructor. Kalau constructor biasanya namanya create, sedangkan destructor namanya harus destroy. Yang perlu diingat yaitu kita harus men-destroy dulu atribut yang bertipe kelas baru kemudian memanggil method Destroy. Ingat, dalam memanggil method destroy harus diawali dengan kata kunci inherited :
 
Destructor TMRUList.Destroy;
Begin
 FMList.Free;
 Inherited Destroy;
End;

Perhatikan, pada baris kode kelas di atas, variable numItems saya hilangkan, karena variable nilainya bisa langsung didapatkan dari atribut yang bertipe TStringList, yaitu dengan memanggil method Count. Berikut ini, baris kode kelas TMRUList setelah numItems dihilangkan :

// Return the number of elements in the MRUList
Function TMruList.Count : Integer;
Begin
 Result := Self.FMList.Count;
End;

// Shift all the elements in the list up by one,
// add new element at the start
Procedure TMruList.Add(s : String);
Var
 i : Integer;
Begin
 Self.FMList.Insert(0, s);
 If Self.FMList.Count >= MRUMaxItems Then
  Self.FMList.Delete( Self.FMList.Count – 1);
End;

Function GetString( n : Integer ) : String;
Begin
 If (n >= 0) and (n <= Self.FMList.Count - 1) Then
  Result := Self.FMList.Strings[n];
End;
Sekian

0 comments:

Post a Comment