Popular Post

My Blog List

Followers

Posted by : Kenji March 12, 2015

Object Pascal, adalah sebuah bahasa dimana delphi menjadi salah satu IDE (Integrated Development Environment) nya, adalah sebuah bahasa yang mendukung penuh konsep OOP. Sederhananya, bahasa ini memungkinkan bagi programmer untuk membuat dan memanipulasi object. Lebih detailnya, bahasa ini mendukung empat prinsip pokok OOP yaitu : Data Abstraction, Encapsulation, Inheritance, Polymorphism.
Mempelajari OOP berbeda dengan mempelajari Delphi. Apalagi bagi seorang yang sudah mengenal bahasa Pascal. Bisa jadi ada orang yang sangat mahir delphi/pascal namun sangat lemah pada konsep OOP.

Apa itu OOP? Apa Itu Object? Apa Itu Kelas?
OOP adalah semua hal yang berkaitan dengan writing programs that manipulate objects : ). Delphi, Java, C++ adalah beberapa contoh bahasa yang mendukung OOP. Ketiga bahasa di atas mempunyai prinsip-prinsip OOP yang sama, tentunya dengan sintaks (penulisan baris kode program) yang berbeda. Sekali kita sudah menguasai konsep OOP, maka akan begitu mudah mempelajari OOP pada bahasa manapun. Karena kita hanya akan fokus pada sistaks, bukan pada apa itu OOP.

Setiap kita mempelajari OOP, maka kita tidak akan lepas dari dua istilah objek dan class (Kelas). Kelas adalah pola/rancangan/struktur data yang dipakai programmer untuk membuat tipe data baru. Untuk mempermudah, kadang saya menyamakan kelas dengan tipe data : ). Setiap bahasa pemrograman mempunyai tipe data bawaan misalnya integer, string, boolean, dll. Delphi dan bahasa lainnya (yang mendukung OOP) memungkinkan bagi programmer untuk membuat tida data sendiri, misalnya Tmahasiswa, Trekening, Tbank, dll. Selama tipe data tersebut bukan tipe data bawaan bahasanya, kita bisa menyebutnya tipe data abstract (abstract data types). VCL (Visual Component Library) milik delphi merupakan contoh koleksi dari banyak kelas. Jadi form, button, combobox, query, dll adalah kelas yang sudah dibuat oleh tim developer embarcadero.

Kita bisa membuat kelas sendiri dan menggunakannya sama dengan kelas-kelas yang ada pada VCL delphi. Kita akan membahsa lebih detail mengenai cara pembuatan dan penggunaan kelas baru pada beberapa artikel berikutnya. Untuk memberikan gambaran awal apa itu kelas perhatikan baris kode berikut ini :

TStudent = class
FNama: string;
FNIS: string;
FAlamat: string;
FTelpon: string;
end;
Baris kode di atas adalah sebuah deklarasi kelas Tstudent dimana kelas tersebut mempunya empat atribut (informasi) yaitu Fnama, FNIS, Falamat, dan Ftelpon. Kita bisa memakai kelas (tipe data) TSTudent ini dengan cara :
Var
Student1 : TStudent;
Student2 : TStudent;

Pada pembahasan di atas, kita sudah membahasa apa itu kelas. Lalu apa itu objek? Hmmm… mudah. Objek adalah instansiasi dari kelas, atau suatu data yang bertipe data kelas. Hmmm mbulet : ). Dari deklarasi di atas, kita bisa perjelas bahwa Student1, Student2 adalah objek dan Tstrudent adalah kelas.

Bekerja dengan Objek
Sebelum kita melanjutkan ke bagian cara deklarasi kelas, kita akan sedikit membahas bagaimana caranya menggunakan kelas dan objek. Kita akan menggunakan TstringList (dawaan delphi) sebagai contoh dalam pembahasan ini.

Var
StringList1 : TStringList; // TStringList > kelas –
// StringList1 objek

Di mana kita harus tuliskan deklarasi di atas? Ini tergantung pada dimana kita akan menggunakan objek ini (scope) berapa lama kita akan menggunakannya (lifetime-nya). Jika kita hanya akan mengakes pada satu method kita, maka deklarasikan pada method tersebut. Misalnya :
Procedure Test;
Var
StringList1 : StringList;
Begin

End;

Pada contoh di atas, variable StringList1 kita deklarasikan pada procedure test. Setelah kita selesai menjalankan procedure test, maka kita sudha tidak bisa mengakses variable StringList1 lagi. Jika kita ingin objek kita ingin objek Stringlist1 ini mempunya skope yang lebih luas dan life time yang lebih lama, kita harus deklarasikan objek ini di luar procedure test. Jika kita deklarasikan objek ini di bagian implementation unit, diluar procedue test, maka objek ini bisa diakses dari semua bagian unit di mana objek ini di deklarasikan. Tapi jika objek ini kita deklarasikan di bagian interface, maka objek ini akan bisa diakses dari semua bagian unit di mana objek ini dideklarasikan dan bisa juga diakses dari unit lainnnya yang mencantumkan unit ini pada bagia uses-nya.


Tanpa memperhatikan dimana kita deklarasikan objek Stringlist1, program kita mempunya kewajaiban untuk mengalokasikan dan membebaskan (jika sudah tidak dipakai) memori. Hal ini yang menjadi perbedaan pokok jika kita bekerja menggunakan variable bertipe objek dan variable bertipe biasa (non objek), misalnya :
Var
i : Integer;

Begin
i := 10;
end

Hanya dengan mendeklarasikannya berarti kita sudah menglokasikan memori untuk variable tersebut. Beda jika yang kita deklarasikan merupakan variable objek. Setelah variable tersebut kita deklarasikan, kita tidak bisa langsung memakainya. Kita harus alokasikan memori dulu untuk variable tersebut, misalnya :
Var
Student1 : TStudent;
Begin
// alokasikan memori sebelum student1 digunakan.
end


Untuk menglakikasikan memori, kita harus memanggil sebuah procedure khusus yang biasa disebut constructor. Procedure Constructor sebuah kelas bisa beragam namanya, bahkan sebuah kelas bisa mempunyai lebih dari satu constructor. Kebanyakan dan biasanya, procedure constructor diberi nama Create. Kita nanti , pada artikel-artikel beikutnya, akan membahas lebih mendalam bagaimana caranya membuat constructor. Cara memanggil contructor yaitu dengan cara menuliskan nama kelasnya sebelum nama constructor tersebut, misalnya :

TStudent1.Create;
TStringlist.Create;

Constructor sebenarnya sebuah fungsi yang mengembalikan sebuah pointer yang mengarah ke memori yang dialokasikan untuk objek tersebut. Contoh yang lebih jelas bisa dilihat di bawah ini :
Var
Student1 : TStudent;
Begin
// Alokasikan memori    

Kesalahan yang sering terjadi bagi yang baru belajar OOP adalah dia lupa memanggil constructornya sebelum digunakan objek yang dia deklarasikan.
Setelah kita alokasikan memori untuk objek tersebut ( dengan memanggil constructor) , kita bisa mengakses data dari objek tersebut dengan menggunakan operator titik (dot) , seperti :
Student1 := TStudent.Create;
Student1.Nama := ‘Bagus’;
Student1.NIS := ‘613990005’;


Jika kita mencoba mengakses data dari objek tersebut tanpa memanggil constructornya, maka akan terjadi error (runtime error)
Oya, dalam sebuah program, kita bisa mendeklarasikan dan menggunakan banyak objek , misalnya :
var
Student1 : TStudent;
Student2 : TStudent;
Begin
// Alokasikan memori
Student1 := TStudent.Create;
Student2 := TStudent.Create;
Dan masing-masing object mempunyai data sendiri-sendiri. Dalam contoh ini (tepatnya yang dideklarasikan di artikel sebelumnya) Student1 mempunyai empat data yaitu Nama,NIS, Alamat dan Telpon, demikian juga Student2.
Student1 := TStudent.Create;
Student2 := TStudent.Create;

Student1.FNama := ‘Bagus Prasojo’;
Student2.FNama := ‘Andi’;
Oya, setiap kita mengalokasikan memori untuk sebuah objek, maka memori itu akan tetap terpakai selama objek tersebut belum di hancurkan (destroy). Oleh karena itu, setiap kita mengalokasikan memori maka kewajiban kita untuk membebaskan memori tersebut setelah objek yang kita buat sudah tidak diperlukan lagi. Jika kita lupa , maka akan terjdi yang namanya memory leak. Apa itu memory leak? Saya membahasnya lebih detail pada artikel ini dan ini, silahkan dibaca. Cara membebaskan memory begitu mudah, tinggal panggil procedure free, misalnya :
Student1.Free;
Student2.Free;
Perhatikan, pola cara membebaskan memori dengan mengalokasikan memori berbeda. Jika kita mengalokasikan memori dengan memanggil funsi create diawali nama kelas, tapi ketika kita membebaskan memori kita panggil procedure free diawali dengan nama objek. Beda ya memanggil procedure diawali dengan nama kelas dan nama objek? Yupe, beda, di artikel-artikel selanjutnya akan kita bahas tentang hal ini.
Di bawah ini contoh penulisan sebuah procedure secara lengkap dimulai dari deklarasi, alokasi memori, dan diakhiri dengan pembebasan memori..

Procedure Test;
Var
StringList1 : StringList; // deklarasi

Begin
// Panggil constructor untuk alokasikan memori
StringList1 := TStringList1.Create;

// ubah dan akses data

// bebaskan memori
StringList1.Free;
End;


Pada contoh di atas, kita mengalokasikan memori dan membebaskan memori pada satu procedure yang sama. Hal ini tidak bermasalah selama objek yang kita alokasikan memori untuknya hanya bisa diakses dari procedure tersebut. Jika objek tersebut bisa diakses dari seluruh bagian unit, maka kita harus hati-hati dalam menentukan kapan kita harus memanggil procedure free (untuk membebaskan memori).

Inti dari apa yang kita bahas di atas tadi adalah, ketika kita mengalokasikan memori untuk sebuah objek, maka kita beranggung jawab untuk membebaskan memori tersebut. Jika kita lupa , maka kemungkinan terjadinya memory leak sangat besar. Namun hal ini sebenarnya tidak sesederhana itu.

Pastikan bebaskan memori yang sudah tidak terpakai !

Perhatikan potongan program di bawah ini :

Procedure Test;
Var
i, j : Integer;
stringList1 : TStringList;

Begin
stringList1 := TStringList.Create;
i := 10;
j := 0;
i := i div j; // baris 10 – menimbulkan Exception
stringList1.Free; // baris 11 – tdk akan pernah dieksekusi
End;


Pada baris ke 10, program akan menampilkan eksepsi devide by zero. Jika kita jalankan kode di atas menggunakan debugger, kita akan lihat bahwa baris ke 11 tidak akan pernah dieksekusi. Memori yang di alokasikan untuk stringList1 tidak pernah dibebaskan. Contoh di atas mungkin akan jarang terjadi, namun yang jelas kita harus hati-hati ketika mengalokasikan memori , kita harus memastikan bahwa memori yang dialokasikan tadi bisa dibebaskan. Delphi menyarankan – dan saya juga – untuk selalu mengapit penulisan Create / Free dengan Try / Finally. Try / Finally merupakan bagian dari standar pemrograman Pascal, cara kerjanya saya jelaskan dibawah ini.

Dalam menggunakan Try/Finally kita akan menjumpai dua buah kelompok baris kode. Kelompok pertama terletak di antara Try dan Finally, sedangkan kelompok kedua terleta di antara finally dan end. Perhatikan potongan baris kode di bawah ini :
Try
kelompok 1
Finally
kelompok 2
End;

Jika ada baris kode di kelompok pertama menimbulkan eksepsi, maka delphi akan menjaankan baris kode yang berada di kelompok kedua sebelum menampilkan eksepsi. Jika kelompok pertama tidak menimbulkan ekspsi baris kode pada kelompok kedua tetap akan dijalankan. Oleh karena itu, baris kode pada kelompok kedua pasti akan diekseusi baik terjadi atau tidak eksepsi pada baris kode di kelompok pertama. Untuk memastikan program bisa membebaskan memori yang sudah tidak terpakai, panggillah procedure free pada kelompok kedua. Lihat pola standar berikut ini :
objek := namakelas.namaconstructor
Try
// Gunakan objek di sini
Finally
.Free;
End;


Perhatikan , kita harus memanggil constructor sebelum baris Try. Hal ini untuk mengantisipasi jika constructor gagal dieksekusi. Jika constructor gagal dieksekusi, delphi tidak akan mengalokasikan memori..Jika constructor dieksekusi setelah baris Try, delphi akan menjalankan baris kode pada kelompok kedua, hal ini akan memungkinkan delphi membebaskan memori yang belum dialokasikan. Dengan menempatkan constructor sebelum try, jika constructornya gagal dieksekusi maka delphi tidak akan mengeksekusi baris kode pada kelompok kedua.
Jika kita harus mengalokasikan dan membebaskan memori untuk lebih dari satu buah objek, penggunaan Try / Finally akan sedikit lebih komplek. Perhatikan potongan baris kode berikut ini :
Var
Student1 : TStudent;
StringListl : TStringList;

Begin
// alokasikan memori
StringListl := TStringList.Create;
Student1 := TStudent.Create;
Try
// akses data Student1 & StringList1
Finally
Student1.Free;
StringList.Free;
End;
Apakah baris kode di atas sudah memastikan procedure free akan dipanggil? Tidak. Jika constructor TStudent gagal dieksekusi, program tidak akan masuk padablok Try,oleh karena itu baris kode pada blok finally tidak akan dieksekusi,dan memori untuk StringList1 tidak akan dibebaskan. Solusi yang bisa kita lakukan adalah :
Var
Student1 : TStudent;
StringListl : TStringList;

Begin
// alokasikan memori
StringListl := TStringList.Create;
Try
Student1 := TStudent.Create;
Try
// akses data Student1 & StringList1
Finally
Student1.Free;
End;
Finally
StringList.Free;
End;

Baris kode di atas bisa dicompile, tapi penulisan baris kode seperti sangat membosankan; coba anda bayangkan jika kita harus create tiga objek atau lebih . Satu trik untuk menyederhanakan baris kode di atas bisa kita buat. Trik ini berdasarkan bahwa Free tidak akan dijalankan jika objeknya nil. Coba cek algoritma precedure Free di bawah ini :

// Delphi’s Free
If theObjectBeingReleased <> Nil Then
ReleaseTheMemory; // Self.Destroy


Sebelum membebaskan memori, procedure Free pertamakali akan mengecek apakah objeknya nil atau tidak. Berarti, apakah baris kode berikut ini aman ?

Var
Student1 : TStudent;
Begin
// Lupa inisialisasi
Student1.Free;


Jawabannya tergantung dari nilai Student1 ketika procedure Free dipanggil. Apakah Student1 nil? Tidak. Di Delphi, variable tidak diberi nilai awal. Perhatikan baris kode di bawah ini (saya jamin tidak akan menimbulkan error) :

Var
Student1 : TStudent;
Begin
Student1 := Nil;

// Lupa inisialisasi Student1
Student1.Free;


Bagaimana baris kode di atas bisa menyederhanakan penulisan baris kode yang mengharuskan kita mengalokasikan memori dan membebaskan memori dari banyak objek? Perhatikan, dengan memehami algoritma procedure Free berarti kita bisa menuliskan baris kode berikut ini :

Student1 := Nil;
Try
Student1 := TStudent.Create;
Finally
Student1.Free;
End;


Jika constructor gagal dijalankan bisa dipastikan procedure Free tidak akan gagal dieksekusi. Kenapa demikian? Ya, karena jika constructor gagal dieksekusi berarti objek tersebut tidak dialokasikan memori untuknya sehingga nilainya tetap nil. Jika objek bernilai nil, ketika dipanggil procedure Free tidak akan menimbulkan error..
Jadi , solusi yang bisa kita ambil ketika kita harus mengalokasikan memori untuk banyak objek bisa seperti baris berikut ini :

Var
Student1 : TStudent;
StringListl : TStringList;

Begin
Student1 := Nil;
StringList1 := Nil;
Try
StringListl := TStringList.Create;
Student1 := TStudent.Create;
// Akses data Student1 dan StringList1
Finally
Student1.Free;
StringList.Free;
End;


Penulisan baris kode yang awal , yaitu menuliskan try/finally di dalam try finally, merupakan solusi yang lebih aman, namun agak ribet. Sedangkan solusi yang kedua (dengan inisialisasi objek menjadi nil) enawarkan solusi penulisan baris kode yang singkat dan enak dibaca. Silahkan anda pilih sendiri.
Berbica mengenai kegagalan dalam membebaskan memori, sebenarnya ada beberapa tool yang bisa membantu kita dalam mendekteksi hal ini. Beberapa contoh antara lain : FastMM dan EukareLog. Silahkan pelajari kedua tool tersebut.

Pada artikel tersebut, kita telah mendeklarasikan kelas sebagai berikut :


Type
 TStudent = Class
  FNama : String;
  FNIS : String;
  FAlamat : String;
  FTelpon : String;
 End;

Jika kita membuat empat objek bertipe TStudent, maka masing-masing objek tersebut akan mempunyai atribut yang sama yaitu nama,nis, alamat dan telpon. Struktur dari masing-masing objek tadi sama persis,dan struktur objek ini ditentukan pada/oleh kelas TStudent.


Atribut-atribut yang ada pada objek student – dalam kasus ini yaitu FNama, FNIS, Falamat ,dan FTelpon, di OOP dikenal dengan beberapa nama. Kadang disebut instance variables, data members, properties dan fields. Hati-hati, jangan terkecoh dengan fields yang berarti kolom pada table.


Jika kita telah terbiasa dengan tipe data Record, tentunya kita akan melihat bahwa struktur sebuah kelas tidak berbeda dengan struktur tipe data record. Keduanya merupakan tipe data yang merupakan gabungan dari beberapa data. Lalu apa yang membedakan kelas dengan tipe data record ? Di dalam kelas, kita bisa membuat procedure (biasa disebut method). Dengan method ini nantinya objek yang kita buat bisa melakukan sesuatu. Method untuk kelas TStudent bisa "RegisterForClass", "SavetoTable", "SendInvoice", dll. Untuk lebih memberi gambaran apa itu method, coba anda buka kelas TstringList dan TiniFile. Sebutkan method-method yang ada pada kedua kelas tersebut.

Saatnya Kita Menuliskan Method


Ada dua langkah yang harus kita lakukan ketika akan membuat sebuah method. Yang pertama, kita harus deklarasikan method tersebut pada bagian deklarasi kelas. Hal ini hampir sama dengan pendeklarasian atribut/properties kelas. Deklarasi ini akan memberitahulan ke compiler method-method apa saja yang dimiliki kelas ini. Method pada kenyataannya sama dengan function atau procedure. Method bisa mengembalikan nilai dan bisa juga menerima parameter. Berikut ini adalah contoh kelas dengan empat atribut dan tiga methods :
Type
 TSquare = Class
  FX, FY : Integer;
  FWidth : Integer;
  Caption : String;
  Function Area : Integer; // hitung luas
  Procedure MoveLeft(dx, dy : Integer); menggerakan ke kiri
  Procedure MoveRight(dx, dy : Integer); menggerakan ke kanan
End;

Langkah selanjutnya yaitu menuliskan baris kode untuk method-method tadi. Kita nanti akan melihat bagaimana cara menuliskan baris kode pada sebuah method , namun sebelum itu coba kita lihat bagaimana kita akan menggunakan method-method tersebut:

Var
 Square1 : TSquare;
 SqWidth : Integer;

Begin
 Square1 := TSquare.Create;
 Try
  Square1.Fx := 10;
  Square1.Fy := 20;
  Square1.FWidth := 7;

  SqWidth := Square1.Area; // 49 nilai yg kita harapkan       Square1.MoveLeft(2, 3);
 Finally
  Square1.Free;
 End;

Seperti yang kita lihat pada baris kode di atas, kita bisa memanggil method dengan menuliskan nama method tersebut diawali dengan nama objeknya (disambung dengan dot/titik) , hal ini sama dengan cara memanggil atribut kelas. Sekarang, jika kita mempunyai dua buah objek bertipe TSquare, dan kita panggil salah satu method, atribut mana yang dipakai oleh method tersebut ? Perhatikan baris kode berikut ini :

Var
 Square1 : TSquare;
 Square2 : TSquare;
 SqWidth : Integer;

Begin
 Square1 := TSquare.Create;
 Square1.FWidth := 7;

 Square2 := TSquare.Create;
 Square2.FWidth := 5;
 SqWidth := Square1.Area; // Hasilnya 49 atau 25?

Berapa nilai sqWidth? Kita inginkan nilainya 49 – yang didapat dari nilai atribut Width x Width. Dan memang demikian. Lalu kenapa bisa nilainya 49 kok bukan 25? Perhatikan, bahwa sebuah method akan menggunakan atribut dari objek yang memanggilnya. Jika kita memanggil method area dari objek Square1 , maka method ini akan menggunakan atribut width milik objek square1 yang bernilai 7.


Sejauh ini kita sudah mengetahui cara mendeklarasikan sebuah method. Selanjutnya kita harus menuliskan baris kode yang merupakan implementasi method yang kita deklarasikan.Kita harus tuliskan baris kode tersebut pada bagian implementation. Bagaimana caranya? Mudah, tuliskan seperti kita menulis sebuah procedure/function seperti biasa. Tapi satu hal yang perlu kita perhatikan. Kita harus bertitahu compiler bahwa procedure yang kita tuliskan bukan procedure seperti biasanya. Caranya dengan menambahkan nama kelas sebelum nama methos (disambung dengan dot/titik). Lihat contoh dibawah ini :

TSquare.Area : Integer;

//dan

Procedure TSquare.MoveLeft(dx, dy : Integer);

Yang perlu anda catat bahwa, kenapa objek yang memanggil method area tidak dijadikan parameter? Lalu bagaimana method – yang aslinya berupa procedure/function biasa – bisa mengakses data dari objek tersebut? Sebenarnya , objek tersebut dijadikan parameter pada method tadi, tapi kita tidak melihatnya, atau lebih tepatnya kita tidak mau menuliskannya. Ketika kita menuliskan baris kode :

SqWidth := Square1.Area; // 49

Compiler sebenarnya mengenerate baris kode :

SqWidth := Area( Square1 )

Jadi secara “Behind the scenes” compiler menjadikan objek sebagai parameter. Di damal method, kita bisa menggunakan “identifier” self untuk mengacu ke objek yang memanggil method tersebut.Ketika kita menuliskan baris kode :
Square1.Area

Di dalam method tersebut Self mengacu ke objek Square1. Jika kita menulis baris kode :

Square2.Area

Berarti Self mengacu ke objek Square2.
Di bawah ini keseluruhan kode untuk method Area:

Function TSquare.Area : Integer;

Begin
 Result := Self.FWidth * Self.FWidth;
End;

Dan di bawah ini keseluruhan kode untuk method MoveLeft dan MoveRight:

Procedure TSquare.MoveLeft( dx, dy : Integer);

Begin
 Self.Fx := Self.Fx – dx;
 Self.Fy := Self.Fy – dy;
End;
Procedure TSquare.MoveRight( dx, dy : Integer);

Begin
 Self.Fx := Self.Fx + dx;
 Self.Fy := Self.Fy + dy;
End;

Pada sebagian besar kasus, penggunaak Self merupakan opsional saja – jadi kita bisa langsung mengakses atribut objek tanpa didahului self, seperti pada baris kode berikut ini :

Function TSquare.Area : Integer;

Begin
 Result := FWidth * FWidth;
End;

Baris kode di atas tidak menimbulkan error. Hal ini karena compiler tahu method yang dipanggil tersebut milik kelas apa, oleh karena itu compiler tahu atribut yang kita akses baik kita menggunakan self atau tidak. . Namun ada satu pengecualian, jika kita mempunyai variable lokal pada method yang namanya sama persis dengan atribut objek, maka untuk mengakses atribut objek harus didahuui dengan self, jika tidak maka compiler akan membaca variable lokal tersebut (bukan atribut objek) , perhatikan contoh di bawah ini :

Function TSquare.Area : Integer;

Var
 FWidth : Integer; 
Begin
 Result := FWidth * FWidth;
End;

Pada method di atas terdapat satu variable lokal bernama Fwidth. Jika kita akses Fwidth tanpa diawalai Self, maka compiler akan memanggil Fwidth (variable lokal) bukan Fwidth (Atribut objek)

Tip

Setelah kita deklarasikan method kita bisa klik Ctrl Shift C –Delphi akan mengenerate kode (hanya outline) di bagian implementation.

Konvensi Penamaan Pada Delphi

Salah satu konvensi pada Delphi adalah nama kelas selalu diawali dengan huruf T (te) yang merupakan sigkatan dari type. Itulah mengapa pada artikel-artikel terdahulu kita menamakan TSquare dan Tstudent bukan Student dan Square. Coba perhatikan kelas-kelas bawaan Dephi semua diawali dengan huruf T (type), mis TButton, TForm, dll.




Konvensi lainnya yaitu nama atribut selalu diawali dengan huruf F (ef), yang merupakan singkatan dari Field. Akan lebih jelas kenapa diawali huruf F (ef) setelah kita mempelajari istilah properties pada artikel-artikel berikutnya. Untuk sekarang ikuti dulu aja : )




Kelas MRU List

Sudah ada beberapa hal tentang OOP yang kita pelajari, namun contoh berikut, yang merupakan contoh yang sering terjadi di dunia nyata akan lebih memperdalam pemahaman kita tentang OOP. Kita akan membuat kelas (tipe data baru) MRUList – yaitu sebuah kelas yang akan dipakai untuk mencatat string yang sering digunakan pada sebuah aplikasi (Most Recently Used). Contoh implementasi MRU antara lain :


1.Produk Microsoft Office, bisa menampilkan file yang paling sering dipakai.
2.Delphi , bisa menampilkan file-file yang baru saja dibuka.


Kita akan membuat sebuah aplikasi di mana user bisa melihat string apa saja yang baru saja dipakai. Karena kita belum mempelajari semua fitur OOP di delphi, kelas yang akan kita buat merupakan kelas yang sederhana dulu. Kita akan mencoba memakai fitur-fitur OOP yang sudah kita pelajari selama ini.
OK, sekarang kita mulai dengan menentukan operasi-operasi apa saja yang akan dilakukan oleh kelas. Kira-kira operasi yang kita butuhkan meliputi :


1.Operasi Query berapa elemen yang ada di list;
2.Operasi untuk menambahkan string pada MRU List;
3.Operasi untuk menampilkan string yang ada pada posisi tertentu;


Ketika kita menambahkan sebuah string pada list, string tersebut akan berada di awal list.Pada aplikasi ini kita harus tentukan jumlah maksimal string yang bisa ditampung di dalam list. Jika sudah mencapai jumlah maksimal, ketika ada string yang ditambahkan lagi, maka kita harus menghapus string yang terakhir dan menempatkan string yang baru pada awal list. Itulah mengapa aplikasi ini disebut MRU (Most Recently Used) List, karena kita dengan aplikasi ini kita bisa mengetahui daftar string apa saja yang baru saja dipakai.
Berikut ini deklarasi awal dari kelas yang akan kita buat :


Type
  TMruList = Class
    Function Count : Integer;
    Procedure Add( s : String);
    Procedure GetString( n : Integer) : String
  End;
Berdasarkan deklarasi kelas di atas, berikut ini contoh penggunaannya :

Var
  muList : TMruList;
  s : String;

Begin
  // inisialisasi objek / alokasikan memori
  mruList := TMruList.Create;
  Try 
    // menambahkan string ke objek
    mruList.Add(‘Spence’);
    mruList.Add(‘Jones’);

    // akses string dalam list
    // string terakhir dipakai berada di index 0
    s := mruList.GetString( 0 );
    // s berisi Jones (string terakhir);
 Finally
  // bebaskan memori
  mruList.Free;
 End;
End;

Pada contoh di atas, kita alokasikan dan membebasan meori pada procedure yang sama. Jika kita menggunakan kelas ini pada sebuah form, maka kita sebaiknya mengalokasikan memori pada saat form dicreate (onCreate Event) dan membebaskan memori pada saat form didestrory (onDestroy event).


OK, sekarang tiba saatnya kita menuliskan baris kode di bagian implementasi kelas. Namun sebelum itu, kita harus tentukan dulu bagaimana caranya menyimpan string pada kelas ini. Solusi terbaik mungkin dengan menggunakan TstringList untuk menyimpan string. Ketika user menambahkan string ke dalam MRUList, kita tambahkan saja string tersebut pada awal stringlist. OK, karena solusi untuk menyimpan string kita gunakan stringlist, maka kita harus deklarasikan sebuah variable yang bertipe TstringList. Kira-kira bagian deklarasi dari kelas TmruLIst seperti di bawah ini :
Type
  TMruList = Class
    FMList : TStringList;
    Function Count : Integer;
    Procedure Add( s : String);
    Procedure GetString( n : Integer) : String
  End;

Dengan demikian kelas di atas harus mengalokasikan memori untuk variable FMList. Kita harus menambahkan baris kode berikut ini :

FMList := TStringList.Create;

Dimana kita harus tambahkan baris kode di atas? Hmmm , perhatikan, proses pengalokasian memori untuk kelas TmruLIst tidak otomatis mengalokasikan memori untuk varable FMList. Kita bisa mengalokasikan memori untuk variable FMList (dengan menambahkan baris kode di atas) pada baris setelah kita alokasikan memori untk kelas TmruList ini. Lihat baris kode berikut :

mruList := TMruList.Create;
mruList.FMList := TStringList.Create;

Tapi cara yang demikian cara yang kurang bagus (poor design) . Dengan cara di atas berarti kita mewajibkan programmer lain yang menggunakan kelas ini untuk melakukan operasi yang berurutan, yaitu mengalokasikan memori untuk kelas, lalu mengalokasikan memori untuk variable FMList. Demikian juga ketika akan melakukan proses membebaskan memori, programmer harus membebaskan memori FMList dulu baru membebaskan memori untuk kelas ini. Hal ini sangat merepotkan dan cenderung menambah resiko kesalahan.



Ada satu solusi untuk masalah di atas, yaitu dengan menyerahkan proses pengalokasian memori pada constructor dan pembebasan memori pada destructor. Cara ini akan kita implementasikan nanti pada artikel berikutnya. Untuk sementara kita akan menggunakan array dengan panjang yang kita tetapkan di awal. Array ini dipakai untuk menampung string. Selain itu kita juga mendeklarasikan satu variable yang akan mencatat berapa string yang digunakan pada satu waktu. Lihat baris kode berikut ini :



Const
 MRUMaxItems = 4;

Type
 TMruList = Class
  FMList : Array[0..MRUMaxItems – 1] of String;
  FNumItems : Integer;
  Function Count : Integer;
  Procedure Add( s : String);
  Function GetString( n : Integer) : String
 End;
Implementation

// Return the number of elements in the MRUList
Function TMruList.Count : Integer;
Begin
 Result := Self.FNumItems;
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
 For i := max(Self.FNumItems, MRUMaxItems - 1] DownTo 1   Do
  Self.FMList[i] := Self.FMList[i – 1];

 Self.MList[0] := s;
 Self.FNumItems := Max(FNumItems + 1, MRUMaxItems);
End;
Function GetString( n : Integer ) : String;
Begin
 If (n >= 0) and (n <= Self.FNumItems - 1) Then
  Result := Self.FMList[n];
End;

Sumber

Leave a Reply

Subscribe to Posts | Subscribe to Comments

- Copyright © 2013 Blog Kuli ah - Fansuber Otaku - Powered by Blogger - Designed by Johanes Djogan -