Chapter sebelumnya menjelaskan mengapa kita membutuhkan OOP; sekarang kita menuliskan class-nya secara utuh. Semua class MATLAB dibangun dari satu struktur berkas yang sama — classdef untuk membuka definisi, properties untuk data, dan methods untuk perilaku — sehingga begitu satu class dikuasai, class lain hanya variasi isi. Pada chapter ini kita merakit class RekeningBank dari nol, menginstansiasi object-nya, dan membandingkannya dengan struct yang selama ini kita pakai. Cakupan materi:
- struktur berkas
classdefdan aturan penamaannya - instansiasi object, akses property, dan pemanggilan method
- dua gaya pemanggilan method: dot notation dan function style
- perbandingan class vs struct
Anatomi classdef #
Aturannya: satu class hidup dalam satu berkas .m yang namanya harus sama dengan nama class — class RekeningBank ditulis di RekeningBank.m. Nama class memakai PascalCase (RekeningBank, KalkulatorStatistik), berbeda dengan fungsi yang kita biasa tulis camelCase. Mekanisme di balik layar: saat MATLAB menemui ekspresi RekeningBank(...), MATLAB mencari berkas RekeningBank.m di path, memuat definisi class-nya sekali, lalu menjalankan constructor. Kerangka minimalnya:
classdef NamaClass
%NAMACLASS Deskripsi singkat class.
properties
% deklarasi property + nilai default
end
methods
% constructor + method lain
end
endMari kita bedah baris-baris kode di atas:
- Baris 1 (
classdef NamaClass): membuka definisi class; berkas harus bernamaNamaClass.m— ketidakcocokan nama membuat class tidak bisa diinstansiasi. - Baris 4-6 (
properties ... end): wadah data; setiap property boleh diberi nilai default yang dipakai saat object baru dibuat. - Baris 8-10 (
methods ... end): wadah perilaku; seluruh function di dalam blok ini otomatis menjadi method milik class. - Baris 11 (
end): penutupclassdef— definisi class berakhir di berkas ini juga.
Blok properties dan methods juga menerima atribut dalam kurung — misalnya properties (Constant = true) atau methods (Static = true) — yang mengubah perilakunya; kita bahas satu per satu pada chapter Properties dan Methods. Atribut level class seperti Sealed (melarang subclass) serta superclass < handle diperkenalkan pada chapter-chapter selanjutnya.
Instansiasi: Membuat Object #
Instansiasi dilakukan dengan memanggil nama class seperti memanggil function: r = RekeningBank('Budi', 1000000). Tiga hal terjadi di balik layar: MATLAB mengalokasikan object baru, mengisi property dengan nilai default, lalu menjalankan constructor untuk menimpa sebagian nilai tersebut. Object yang dihasilkan bisa diperiksa identitasnya:
>> r = RekeningBank('Budi', 1000000);
>> class(r)
>> whosans =
'RekeningBank'
Name Size Bytes Class Attributes
r 1x1 112 RekeningBankKolom Class pada whos kini memuat RekeningBank — bukan double atau struct — sehingga type data buatan kita tampil setara dengan type bawaan MATLAB. Tanpa titik koma, object menampilkan ringkasan property-nya:
>> r = RekeningBank('Budi', 1000000)r =
RekeningBank with properties:
pemilik: 'Budi'
saldo: 1000000Dua Gaya Memanggil Method #
Aturannya: setiap method menerima object sebagai argumen pertama, dan MATLAB menyediakan dua gaya pemanggilan yang setara — r.hitungBunga(0.03) (dot notation) dan hitungBunga(r, 0.03) (function style). Mekanismenya: dot notation berarti “mintalah object r menjalankan method hitungBunga”, sedangkan function style membuat MATLAB melihat class dari argumen pertama lalu mengirimkan r sebagai argumen pertama method tersebut. Keduanya menulis argumen sisanya dengan urutan yang sama. Gaya pertama lebih umum karena membaca alami dari kiri ke kanan; gaya kedua berguna ketika method di-function_handle-kan atau dipass sebagai argumen. Keduanya diuji pada uji_RekeningBank.m di bawah.
Class vs Struct: Kapan Class Menang #
Struct dan class sama-sama menyimpan data berlabel, jadi kapan class lebih baik? Perbedaannya ada pada penjagaan aturan: field struct terbuka untuk siapa pun, sedangkan property class melewati constructor dan method yang bisa memvalidasi. Tabel berikut merangkum pertimbangannya:
| Aspek | struct | class (classdef) |
|---|---|---|
| Validasi nilai | tidak ada — field menerima apa saja | di constructor dan method |
| Perilaku menyatu dengan data | tidak — fungsi terpisah | ya — method dalam classdef |
| Nilai default terkontrol | manual tiap kali membuat | otomatis tiap instansiasi |
| Cocok untuk | data sekali pakai, konfigurasi | entitas dengan aturan dan state |
Perbandingan langsungnya tampak pada uji_RekeningBank.m: constructor RekeningBank menolak saldo awal negatif dengan pesan galat, sementara struct menerima assignment s.saldo = 'delapan juta' tanpa protes — field berubah tipe sekaligus kehilangan makna, dan class-nya pun bukan object (isobject(s) mengembalikan 0).
Contoh Lengkap: RekeningBank #
Class berikut menyimpan pemilik dan saldo, lalu menegakkan aturan “setoran harus positif” serta “penarikan tidak boleh melebihi saldo”:
classdef RekeningBank
%REKENINGBANK Rekening tabungan sederhana (value class).
properties
pemilik = 'Tanpa Nama'
saldo = 0
end
methods
function obj = RekeningBank(pemilik, saldoAwal)
if nargin < 2
saldoAwal = 0;
end
if nargin < 1
pemilik = 'Tanpa Nama';
end
if ~ischar(pemilik) || isempty(strtrim(pemilik))
error('RekeningBank:pemilikTidakValid', ...
'pemilik harus teks non-kosong.');
end
if ~isscalar(saldoAwal) || ~isnumeric(saldoAwal) || saldoAwal < 0
error('RekeningBank:saldoTidakValid', ...
'saldo awal harus skalar >= 0.');
end
obj.pemilik = pemilik;
obj.saldo = saldoAwal;
end
function obj = setor(obj, jumlah)
if ~isscalar(jumlah) || ~isnumeric(jumlah) || jumlah <= 0
error('RekeningBank:jumlahTidakValid', ...
'jumlah setor harus skalar positif.');
end
obj.saldo = obj.saldo + jumlah;
end
function obj = tarik(obj, jumlah)
if ~isscalar(jumlah) || ~isnumeric(jumlah) || jumlah <= 0
error('RekeningBank:jumlahTidakValid', ...
'jumlah tarik harus skalar positif.');
end
if jumlah > obj.saldo
error('RekeningBank:saldoKurang', ...
'saldo %g tidak cukup untuk tarik %g.', ...
obj.saldo, jumlah);
end
obj.saldo = obj.saldo - jumlah;
end
function b = hitungBunga(obj, tingkatTahunan)
b = obj.saldo * tingkatTahunan;
end
function tampilkanInfo(obj)
fprintf('%s | saldo Rp%.2f\n', obj.pemilik, obj.saldo);
end
end
endMari kita bedah baris-baris kode di atas:
- Baris 8-25 (
function obj = RekeningBank(pemilik, saldoAwal)): constructor — argumen keduanya opsional (nargin), lalu dua pemeriksaan menolak pemilik kosong dan saldo negatif sebelum property diisi. - Baris 26-32 (
setor): method pengubah — validasi jumlah lebih dulu, kemudianobj.saldoditambah. Perhatikan variabel outputnyaobj: class ini value class, sehingga hasil perubahan harus di-return dan pemanggil menulisr = r.setor(...). - Baris 33-44 (
tarik): selain validasi jumlah, barisif jumlah > obj.saldomenjaga invariant saldo tak negatif — aturan yang pada versi prosedural Chapter Konsep OOP berhasil dilanggar. - Baris 45-50 (
hitungBunga,tampilkanInfo): dua method pembaca — yang pertama mengembalikan nilai (b), yang kedua langsung menampilkan ke Command Window.
Skrip uji uji_RekeningBank.m menjalankan seluruh alur tersebut:
% uji_RekeningBank.m - menguji class RekeningBank
r = RekeningBank('Budi', 1000000);
r.tampilkanInfo();
r = r.setor(250000); % value class: objek baru di-bind ulang ke r
r.tampilkanInfo();
r = r.tarik(300000);
r.tampilkanInfo();
fprintf('bunga 3%% per tahun : Rp%.2f\n', hitungBunga(r, 0.03)); % function style
fprintf('class r : %s\n', class(r));
d = RekeningBank(); % tanpa input -> nilai default
d.tampilkanInfo();
try
RekeningBank('Siti', -100);
catch err
fprintf('ditolak : %s\n', err.message);
end
% --- perbandingan dengan struct: aturan tidak dijaga ---
s = struct('pemilik', 'Siti', 'saldo', 1000000);
s.saldo = 'delapan juta'; % struct menerima apa saja
fprintf('struct s.saldo : %s\n', s.saldo);
fprintf('class s : %s\n', class(s));
fprintf('s adalah object : %d\n', isobject(s));Output yang Dihasilkan:
Budi | saldo Rp1000000.00
Budi | saldo Rp1250000.00
Budi | saldo Rp950000.00
bunga 3% per tahun : Rp28500.00
class r : RekeningBank
Tanpa Nama | saldo Rp0.00
ditolak : saldo awal harus skalar >= 0.
struct s.saldo : delapan juta
class s : struct
s adalah object : 0Ringkasan #
Class ditulis dalam berkas bernama sama dengan class-nya: classdef ... end membungkus blok properties (data beserta nilai default) dan methods (perilaku). Instansiasi r = RekeningBank(...) menjalankan constructor dan menghasilkan object yang teridentifikasi lewat class(r) serta kolom Class pada whos. Method dipanggil dengan dot notation obj.metode(x) atau function style metode(obj, x) — keduanya setara. Dibanding struct, class menang ketika data perlu dijaga aturan: constructor dan method kita menjadi satu-satunya pintu perubahan. Berkas RekeningBank.m dan uji_RekeningBank.m di bagian bawah halaman memuat seluruh kode yang sudah teruji.