{ }
OOP
@
::
Mobile Development • Flutter & Dart

BAB 3 — OBJECT ORIENTED PROGRAMMING

Kelas 10  •  Semester 1  •  Buku Digital Interaktif

Lanjutan dari BAB 1 (Pengenalan Mobile Dev) & BAB 2 (Dasar Dart)

Navigasi

Daftar Isi

Klik topik mana pun untuk langsung melompat ke materinya.

Tujuan Pembelajaran

Setelah BAB ini, kamu akan bisa…

  • Menjelaskan apa itu Class dan Object dengan kata-katamu sendiri.
  • Membuat class Dart lengkap dengan constructor, property, dan method.
  • Membedakan 4 pilar OOP: Encapsulation, Inheritance, Polymorphism, Abstraction.
  • Menghubungkan konsep OOP ke dunia nyata lewat analogi sederhana.
  • Membangun Mini Project Sistem Data Mahasiswa memakai OOP.
  • Menyelesaikan 3 latihan & tugas akhir BAB secara mandiri.

🔗 Keterkaitan dengan BAB sebelumnya

BAB 1 mengenalkan dunia mobile. BAB 2 mengajarkan dasar Dart (variabel, tipe data, fungsi). BAB 3 menggabungkannya: kita mulai berpikir dalam bentuk objek — cara berpikir yang dipakai Flutter di setiap widget.

🔷 Konsep 1 — Class

Apa itu Class?

1. Class Adalah Cetakan

Class adalah cetakan atau rancangan untuk membuat sesuatu. Misalnya cetakan rumah.

Class digunakan untuk membuat Objek

2. Menyimpan Data & Aksi

Dalam sebuah class biasanya terdapat dua hal utama:

  • Data (Property): Atribut seperti nama, usia
  • Aksi (Method): Perilaku seperti perkenalan(), belajar()

3. Class Belum Menjadi Benda

Class hanyalah rancangan. Selama belum dibuat menjadi objek, class belum bisa digunakan secara langsung (bukan benda yang nyata).

Contoh Kode Class Dart

class Mahasiswa {
  String nama = "";
  int usia = 0;

  void perkenalan() {
    print("Halo");
  }
}

Penjelasan Struktur Kode:

class Mahasiswa Nama class
String nama Property (Data)
int usia Property (Data)
perkenalan() Method (Aksi)
🔷 Konsep 2 — Property

Property = Data (Atribut Milik Class)

🪪 Analogi: Data pada Kartu Mahasiswa

🧑‍🎓
namaBudi
usia16
jurusanPPLG

Variabel yang ada di dalam class disebut Property. Fungsinya menyimpan data atau ciri-ciri dari objek.

Penjelasan Teknis

  • Property adalah variabel yang dideklarasikan di dalam class.
  • Menyimpan informasi/keadaan (state).
  • Contoh pada class Mahasiswa: nama dan usia.
class Mahasiswa {
  // Property (Data)
  String nama = "";
  int usia = 0;
}
🔷 Konsep 3 — Method

Method = Aksi / Perilaku (Kemampuan Class)

🏃 Analogi: Kemampuan / Aksi Mahasiswa

🧍 Klik salah satu method di bawah ▼

Fungsi yang ada di dalam class disebut Method. Fungsinya melakukan sebuah tindakan atau perilaku.

Penjelasan Teknis

  • Method adalah fungsi yang dibuat di dalam class.
  • Mengatur tindakan/perilaku yang dapat dilakukan.
  • Contoh method: perkenalan() dan belajar().
class Mahasiswa {
  String nama = "";

  // Method (Aksi)
  void perkenalan() {
    print("Halo");
  }

  void belajar() {
    print("Sedang belajar...");
  }
}
🔷 Konsep 4 — Object

Object = Hasil Cetakan Nyata

🏠 Analogi: Blueprint Rumah → Rumah Nyata

Blueprint Rumah ↓ dibangun ↓ 🏠 Rumah 1
Blueprint Rumah ↓ dibangun ↓ 🏠 Rumah 2
Blueprint Rumah ↓ dibangun ↓ 🏠 Rumah 3

Penjelasan Teknis

  • Object adalah bentuk nyata (instance) yang diciptakan dari Class.
  • Jika Class adalah cetakan, maka Object adalah benda hasil cetakannya.

Satu blueprint dapat digunakan untuk membuat banyak rumah yang bentuknya sama.

🔷 Konsep 5 — Membuat Object

Mencetak Objek dari Blueprint

Nah, sekarang blueprint ini kita pakai untuk mencetak objek!

Penjelasan Teknis

  • Di dalam fungsi main(), kita memanggil nama class Mahasiswa() untuk mencetak objek.
  • Objek yang dibuat disimpan ke dalam variabel (misalnya m).
class Mahasiswa {
  String nama = "";
  int usia = 0;
}

void main() {
  // Blueprint Mahasiswa dipakai untuk mencetak objek m
  var m = Mahasiswa();
}
Terminal Output
Klik “Jalankan Kode” untuk melihat hasilnya ▸
🔷 Konsep 6 — Mengakses Property

Mengisi & Membaca Data Objek

Penjelasan Teknis

  • Gunakan tanda titik (.) setelah nama objek untuk mengakses property-nya.
  • Contoh mengisi data: m.nama = "Budi";
  • Contoh membaca data: print(m.nama);
class Mahasiswa {
  String nama = "";
  int usia = 0;
}

void main() {
  var m = Mahasiswa();

  // Mengisi property (Data)
  m.nama = "Budi";
  m.usia = 16;

  // Membaca property (Data)
  print(m.nama);
  print(m.usia);
}
Terminal Output
Klik “Jalankan Kode” untuk melihat hasilnya ▸
🔷 Konsep 7 — Memanggil Method

Menjalankan Aksi / Perilaku Objek

Penjelasan Teknis

  • Sama seperti property, method dipanggil menggunakan tanda titik (.) diikuti kurung buka-tutup ().
  • Contoh memanggil method: m.perkenalan();
class Mahasiswa {
  String nama = "";

  void perkenalan() {
    print("Halo, saya $nama");
  }
}

void main() {
  var m = Mahasiswa();
  m.nama = "Budi";

  // Memanggil method (Aksi)
  m.perkenalan();
}
Terminal Output
Klik “Jalankan Kode” untuk melihat hasilnya ▸
🔷 Konsep 8 — Constructor (Bagian 1)

Kenapa Kita Butuh Constructor?

❌ Masalah: Tanpa Constructor

Tanpa constructor, data harus diisi satu per satu secara manual setelah object dibuat.

class Mahasiswa {
  String nama = "";
  int usia = 0;
}

void main() {
  var mhs = Mahasiswa(); // Objek dibuat dulu

  mhs.nama = "Sari";    // Harus diisi 1 per 1
  mhs.usia = 16;        // Merepotkan jika data banyak!
}

✅ Solusi: Menggunakan Constructor

Constructor membuat pengisian data menjadi jauh lebih cepat & praktis (langsung saat object dibuat).

class Mahasiswa {
  String nama;
  int usia;

  // Constructor
  Mahasiswa(this.nama, this.usia);
}

void main() {
  // Data LANGSUNG diisi saat objek dicetak!
  var mhs = Mahasiswa("Sari", 16);
}
Kesimpulan Utama Constructor memangkas kode pengisian data sehingga pembuatan objek menjadi instan dan bersih.
🔷 Konsep 8 — Constructor (Bagian 2)

Memahami Kata Kunci this secara Sederhana

Perhatikan baris sintaks constructor berikut: Mahasiswa(this.nama, this.usia);

Apa arti this?

this.nama nama milik Object
nama data yang dikirim saat membuat object

Contoh Pemetaan Data

Saat kita memanggil:

var mhs = Mahasiswa("Sari", 16);
this.nama "Sari"
this.usia 16
🔷 Konsep 8 — Constructor (Bagian 3)

Kapan Constructor Berjalan?

Constructor itu jalan kapan? ➜ Jawabannya: Saat Mahasiswa() dipanggil!

1. Class Mahasiswa Blueprint Siap
2. Dipanggil Mahasiswa("Sari", 16)
3. Constructor Jalan Isi nama & usia
4. Objek Siap Sari (16 tahun)

Kode Lengkap

class Mahasiswa {
  String nama;
  int usia;

  // Constructor
  Mahasiswa(this.nama, this.usia);
}

void main() {
  // Constructor dipanggil di sini
  var mhs = Mahasiswa('Sari', 16);

  print('${mhs.nama}, ${mhs.usia} tahun');
}

Terminal & Output

Terminal Output
Klik “Jalankan Kode” untuk melihat hasilnya ▸
🔷 Konsep 9 — Apa Itu OOP?

Object Oriented Programming (OOP)

💡 OOP adalah cara membuat program dengan konsep objek.

Dunia nyata Dibuat menjadi Objek dalam program

🚗 Contoh Dunia Nyata: Mobil

Data (Ciri):

  • warna
  • merk
  • tahun

Aksi (Perilaku):

  • jalan()
  • rem()
  • nyala()

💻 Di Dalam Program: Object Mobil

Property (Data):

  • String warna;
  • String merk;

Method (Aksi):

  • void jalan()
  • void rem()
🔷 Konsep 10 — Kenapa OOP?

Kenapa Menggunakan OOP?

❌ Tanpa OOP

Data dan fungsi tersebar secara terpisah di mana-mana.

Dampaknya Sulit:

  • Dikelola saat program makin besar
  • Dikembangkan oleh tim
  • Digunakan ulang (reuse)

✅ Dengan OOP

Data + aksi dikumpulkan rapat dalam satu Object.

Keuntungannya Lebih:

  • Rapi dan terstruktur
  • Mudah dipahami alurnya
  • Mudah dikembangkan
🛡️ Fondasi OOP

4 Pilar Utama OOP

Dalam Object Oriented Programming, ada 4 konsep utama (pilar) yang melindungi dan menstrukturkan kode kita:

1. Encapsulation

🔒 Melindungi data

Menjaga data agar tidak bisa diubah sembarangan dari luar.

2. Inheritance

🧬 Pewarisan sifat

Mewariskan atribut & aksi dari class induk ke class anak.

3. Polymorphism

🎭 Banyak bentuk

Satu nama method, namun memiliki perilaku berbeda-beda.

4. Abstraction

⚙️ Menyembunyikan detail

Menyembunyikan kerumitan mesin di balik antarmuka sederhana.

🛡️ Pilar OOP 1 — Encapsulation

Encapsulation = Melindungi Data agar Tidak Diubah Sembarangan

❌ Masalah: Tanpa Encapsulation

Saldo bisa diubah sembarangan jadi minus. Ini tidak masuk akal!

class Dompet {
  double saldo = 0;
}

void main() {
  var d = Dompet();
  
  // Saldo diubah sembarangan dari luar!
  d.saldo = -50000; 
}

✅ Solusi: Dikunci 🔒 & Diubah lewat Aturan

Gunakan _ agar private, lalu ubah lewat method dengan validasi aturan.

class Dompet {
  double _saldo = 0; // Private (dikunci 🔒)

  void setor(double jumlah) {
    if (jumlah > 0) { // Aturan aman
      _saldo += jumlah;
    }
  }

  double get saldo => _saldo;
}

🔒 Data Pribadi ➜ Dilindungi (Private _) ➜ Akses Hanya Lewat Aturan (setor())

Orang luar tidak boleh mengambil/mengubah uang langsung di dompetmu. Harus melalui aturan!

🛡️ Pilar OOP 1 — Encapsulation (Bagian 2)

Getter — Cara Aman Mengambil Data Private

❓ Masalah: Data Sudah Dikunci

Setelah _saldo dikunci dengan _, bagaimana cara kita membaca nilainya dari luar class?

var dompet = Dompet();

// ❌ INI DILARANG! Tidak bisa akses dari luar.
print(dompet._saldo);

// Error: '_saldo' isn't defined for the class
Analogi: Getter = Hanya Melihat 👀 Seperti jendela kaca di brankas bank — kamu bisa melihat saldo, tapi tidak bisa mengambil uang langsung.

✅ Solusi: Gunakan Getter

Getter adalah pintu baca yang kita buat secara sengaja untuk mengizinkan pembacaan data private.

class Dompet {
  double _saldo = 0; // Private 🔒

  // Cara ringkas (arrow)
  double get saldo => _saldo;

  // Cara blok (sama artinya)
  double get saldo {
    return _saldo;
  }
}

Cara Pakai Getter

void main() {
  var dompet = Dompet();
  dompet.setor(50000);

  // ✅ Akses via getter — seperti variabel biasa!
  print(dompet.saldo);
}
Terminal Output
Klik “Jalankan Kode” untuk melihat hasilnya ▸

👀 Getter = double get saldo => _saldo;  |  Izin BACA saja, tidak bisa ubah

Pengguna cukup tulis dompet.saldo — terasa seperti property biasa, padahal ada perlindungan di baliknya.

🛡️ Pilar OOP 1 — Encapsulation (Bagian 3)

Setter — Mengubah Data dengan Aturan Ketat

Apa itu Setter?

Setter adalah pintu tulis yang memungkinkan kita mengubah nilai private variable — tetapi hanya jika memenuhi aturan/validasi yang sudah kita tetapkan.

class Dompet {
  double _saldo = 0;

  // Getter (baca)
  double get saldo => _saldo;

  // Setter (tulis + validasi)
  set saldo(double jumlah) {
    if (jumlah >= 0) {
      _saldo = jumlah; // ✅ aman, diterima
    } else {
      print('Saldo tidak boleh negatif'); // ❌ ditolak
    }
  }
}

Demo: Setter dengan Validasi

void main() {
  var dompet = Dompet();

  // ✅ Saldo valid — diterima
  dompet.saldo = 100000;
  print(dompet.saldo);

  // ❌ Saldo negatif — ditolak setter
  dompet.saldo = -50000;
}
Terminal Output
Klik “Jalankan Kode” untuk melihat hasilnya ▸

✏️ Sintaks Setter

set Kata kunci untuk mendefinisikan setter
saldo Nama setter (sama dengan getter-nya)
(jumlah) Parameter nilai baru yang diterima
🛡️ Pilar OOP 1 — Encapsulation (Bagian 4)

Peta Lengkap Encapsulation

🗺️ Hubungan Antar Bagian

ENCAPSULATION
Private Variable
_saldo
Method Akses
Getter 👀
Membaca
Setter ✏️
Mengubah
Tabel Wajib Encapsulation Kelas 11
Materi Status
Class & Object✅ Wajib
Constructor✅ Wajib
Private Variable _✅ Wajib
Method✅ Wajib
Getter✅ Wajib
Setter✅ Wajib
Validasi Setter✅ Wajib

⚖️ Getter/Setter vs Method Biasa

❌ Method Biasa (Kurang Elegan)

// Versi method biasa
double getSaldo() { return _saldo; }
void setSaldo(double val) { _saldo = val; }

// Cara pakainya:
print(dompet.getSaldo()); // perlu ()
dompet.setSaldo(50000);   // tidak intuitif

✅ Getter/Setter Dart (Lebih Bersih)

// Versi getter/setter Dart
double get saldo => _saldo;
set saldo(double val) { _saldo = val; }

// Cara pakainya:
print(dompet.saldo);  // seperti property biasa!
dompet.saldo = 50000; // intuitif & natural

💡 Intinya: Getter/Setter membuat sintaks terasa alami seperti variabel biasa — tapi ada penjaga (validasi) di balik layar!

🧬 Pilar OOP 2 — Inheritance (Bagian 1)

Inheritance = Pewarisan Sifat

👨‍👩‍👧 Analogi: Silsilah Keluarga

👨‍🦰
Orang
🧬 🧬
🎓
Mahasiswa
👨‍🏫
Dosen

Gen 🧬 mengalir turun. Mahasiswa & Dosen mewarisi sifat dari Orang.

🗂️ Diagram: Parent & Child Class

Parent Class
Orang
│ extends
┌─┘
Child Class
Mahasiswa
└─┐
Child Class
Dosen
Parent Class = kelas induk
Child Class = kelas turunan
extends = mewarisi

📦 Apa Saja yang Diwariskan?

✔️Property — atribut & data
✔️Method — aksi & fungsi
Constructor — tidak diwariskan!
💡 Constructor tidak diwariskan, itulah mengapa child class menggunakan super() untuk menginisialisasi data parent.

🔑 Keyword extends

class Mahasiswa extends Orang
Mahasiswa class anak (Child Class)
extends kata kunci pewarisan
Orang class induk (Parent Class)
📖 Dibaca: “Mahasiswa adalah turunan dari Orang.”

🌍 Contoh Dunia Nyata

Kendaraan
Mobil Motor Truk
Hewan
Kucing Anjing Burung
🬔 Pilar OOP 2 — Inheritance (Bagian 2)

Memahami super() dan Method Warisan

⚡ Apa itu super(nama)?

Constructor tidak diwariskan. Child class perlu cara untuk mengisi data parent — caranya: panggil super()!

Mahasiswa(String nama, this.nim)
    : super(nama);
super(nama)
memanggil constructor milik Orang
Orang(this.nama);  ← nama tersimpan!

🤔 Kenapa m.sapa() Bisa Dipanggil?

Mahasiswa tidak mendefinisikan sapa() — tapi kenapa bisa dipanggil?

Mahasiswa tidak punya method sapa()
tetapi Orang punya sapa()
karena Mahasiswa extends Orang (inheritance)
✓ Mahasiswa ikut memiliki sapa()

Kode Lengkap

class Orang {
  String nama;
  Orang(this.nama);
  void sapa() => print('Halo, saya $nama');
}

class Mahasiswa extends Orang {
  String nim;
  Mahasiswa(String nama, this.nim)
      : super(nama);
}

void main() {
  var m = Mahasiswa('Budi', '2024001');
  m.sapa(); // method warisan dari Orang
}
Terminal Output
Klik “Jalankan Kode” untuk melihat hasilnya ▸

🧠 Ilustrasi Memori — Object Mahasiswa

Ketika objek m dibuat, di dalam memori tersimpan 2 data:

📦 Object: m (Mahasiswa)
nama = "Budi" ← dari Orang (parent)
nim = "2024001" ← milik Mahasiswa
🬔 Pilar OOP 2 — Inheritance (Bagian 3)

Keuntungan Inheritance & Catatan Penting

❌ Tanpa Inheritance — Kode Berulang

Setiap class harus mendefinisikan hal yang sama berulang-ulang:

class Mahasiswa
- nama
- sapa()
class Dosen
- nama   ← diulang!
- sapa() ← diulang!
class Admin
- nama   ← diulang!
- sapa() ← diulang!
kode diulang berkali-kali 😵

✔️ Dengan Inheritance — Efisien & Rapi

Definisikan sekali di parent, sisanya tinggal extends:

class Orang
- nama
- sapa()
↓ extends
Mahasiswa ✓
Dosen ✓
Admin ✓
cukup extends — semua ikut mewarisi 🎉
⚠️
Catatan Penting — Jangan Salah Paham!

Inheritance bukan berarti menyalin kode.

Yang terjadi adalah: child class memperoleh akses terhadap property dan method dari parent class.

💡 Kode class Orang tetap ada di satu tempat. Mahasiswa dan Dosen hanya mendapat hak akses — bukan salinan kodenya.

🬔 Pilar OOP 2 — Inheritance (Bagian 4)

Alur Eksekusi Kode — Dari main() Sampai Output

📊 Urutan Eksekusi Step-by-Step

1 main() mulai dijalankan
2 Mahasiswa("Budi", "2024001") dipanggil
3 constructor Mahasiswa mulai berjalan
4 super(nama) → constructor Orang dipanggil
5 nama = "Budi" tersimpan (dari Orang)
6 nim = "2024001" tersimpan (milik Mahasiswa)
7 objek m selesai dibuat 🎉
8 m.sapa() dipanggil dari main()
9 method sapa() milik Orang dijalankan
Output: “Halo, saya Budi”

Kode Referensi (dengan anotasi)

class Orang {
  String nama;
  Orang(this.nama);         // ← step 4 & 5
  void sapa() =>            // ← step 9
    print('Halo, saya $nama');
}

class Mahasiswa extends Orang {
  String nim;
  Mahasiswa(String nama, this.nim) // ← step 3
      : super(nama);             // ← step 4
}

void main() {               // ← step 1
  var m = Mahasiswa(         // ← step 2
    'Budi', '2024001'
  );                         // ← step 7
  m.sapa();                  // ← step 8
}
Terminal Output
Klik “Jalankan Kode” untuk melihat hasilnya ▸

💡 super() selalu jalan sebelum body constructor child — memastikan data parent sudah siap lebih dahulu!

🛡️ Pilar OOP 3 — Polymorphism

Polymorphism = Suara yang Berbeda

🐶 Analogi: Setiap Makhluk Bersuara

🧑
"Halo!"
🐶
"Guk!"
🐱
"Meong!"

Method bersuara() sama, tetapi hasilnya berbeda untuk tiap objek. Satu nama method, banyak bentuk perilaku.

Penjelasan Teknis

  • @override menulis ulang method milik parent.
  • Objek berbeda merespons method sama secara berbeda.
  • Membuat kode fleksibel & mudah diperluas.
class Hewan {
  void bersuara() => print('...');
}
class Anjing extends Hewan {
  @override
  void bersuara() => print('Guk guk!');
}
class Kucing extends Hewan {
  @override
  void bersuara() => print('Meong!');
}

void main() {
  List<Hewan> hewan = [Anjing(), Kucing()];
  for (var h in hewan) h.bersuara(); // method sama, hasil beda
}
Terminal Output
Klik “Jalankan Kode” untuk melihat hasilnya ▸
🛡️ Pilar OOP 3 — Polymorphism (Bagian 2)

Method vs Getter — Jangan Sampai Ketukar! 🎭

❓ Pertanyaan Sering Muncul:

"Apakah void bersuara() itu getter atau function?"

Jawabannya: Bukan Getter!

Ini adalah Method (fungsi yang berada di dalam class).

void bersuara() Method (Ada tanda ())
String get nama Getter (TIDAK pakai ())

📊 Perbandingan Sintaks & Pemanggilan

Jenis Deklarasi Pemanggilan
Method void bersuara() h.bersuara(); (pakai ())
Getter String get nama orang.nama; (tanpa ())
// Contoh Getter vs Method:
class Orang {
  String _nama = "Rifqi";
  String get nama => _nama; // Getter (tanpa ())
}

// Pemanggilan:
print(orang.nama);     // Getter: tanpa ()
orang.bersuara();      // Method: pakai ()
🛡️ Pilar OOP 3 — Polymorphism (Bagian 3)

Bedah Kode: Parent Class (Hewan) 🦴

Blueprint Induk

Kita mulai dari membuat class induk bernama Hewan sebagai standar perilaku dasar.

class Hewan {
  // Method dasar bersuara
  void bersuara() => print('...');
}

💡 Versi Panjang (Tanpa Arrow Function)

class Hewan {
  void bersuara() {
    print("...");
  }
}

Tanda => (Arrow Function) hanyalah penulisan singkat untuk fungsi yang cuma berisi 1 baris kode.

🔍 Penjelasan Komponen Blueprint

class Hewan Membuat blueprint bernama Hewan
bersuara() Method default milik induk
print('...') Suara default sebelum diubah

"Parent Class menyiapkan fondasi. Setiap hewan PASTI bisa bersuara, tetapi suaranya belum spesifik."

🛡️ Pilar OOP 3 — Polymorphism (Bagian 4)

Child Class & Konsep @override 🐶🐱

Mewarisi & Menimpa Method

class Anjing extends Hewan {
  @override
  void bersuara() => print("Guk guk!");
}

class Kucing extends Hewan {
  @override
  void bersuara() => print("Meong!");
}

⚡ Apa itu @override?

@override berarti: "Saya tidak membuat method baru, melainkan MENIMPA (mengganti) isi method lama milik parent."

  • Parent (Hewan): print('...')
  • Anjing: ditimpa jadi print('Guk guk!')
  • Kucing: ditimpa jadi print('Meong!')

📊 Struktur Hierarki Kelas

Hewan
bersuara() ➜ print("...")
┌───────┴────────┐
Anjing
bersuara()
"Guk guk!"
Kucing
bersuara()
"Meong!"
🛡️ Pilar OOP 3 — Polymorphism (Bagian 5)

Konsep IS-A & List<Hewan> 🗃️

Pembuatan List di main()

void main() {
  // Membuat List bertipe Hewan
  List<Hewan> hewan = [
    Anjing(),
    Kucing()
  ];
}

❓ Kenapa bertipe List<Hewan>?

Yang dibuat bukan List<Anjing>, melainkan List<Hewan>. Kenapa Anjing dan Kucing boleh masuk ke dalam satu List yang sama?

💡 Hubungan IS-A (Adalah)

  • Anjing IS-A Hewan (Anjing adalah seekor Hewan)
  • Kucing IS-A Hewan (Kucing adalah seekor Hewan)

Karena keduanya adalah Hewan, maka wadah bertipe List<Hewan> sah dan berhak menampung objek Anjing maupun Kucing!

📦 Struktur List<Hewan> dalam Memori
[0] Index 0Anjing()
[1] Index 1Kucing()
🛡️ Pilar OOP 3 — Polymorphism (Bagian 6)

Simulasi Memori & Perulangan Loop 🧠

Perulangan Kode

for (var h in hewan) {
  h.bersuara();
}

🔄 Cara Kerja Loop for-in

Loop mengambil isi List<Hewan> satu per satu secara bergantian dan menyimpannya sementara ke variabel h.

📍 Iterasi Pertama

h Anjing()

Variabel h menunjuk ke objek Anjing di memori.

📍 Iterasi Kedua

h Kucing()

Variabel h berpindah menunjuk ke objek Kucing di memori.

🛡️ Pilar OOP 3 — Polymorphism (Bagian 7)

Penelusuran Baris demi Baris (Eksekusi) 🔍

🔍 Eksekusi h.bersuara()

Perhatikan bagaimana program bertindak saat mengeksekusi h.bersuara():

Iterasi 1 (Isi h = Anjing):
h.bersuara() ➜ sebenarnya Anjing().bersuara()
Output ➜ "Guk guk!"
Iterasi 2 (Isi h = Kucing):
h.bersuara() ➜ sebenarnya Kucing().bersuara()
Output ➜ "Meong!"

🗺️ Alur Visual Komputer

Awal: h
Pertama: h = Anjing()
Jalankan: Anjing().bersuara()"Guk guk!"
Lanjut: h = Kucing()
Jalankan: Kucing().bersuara()"Meong!"
🛡️ Pilar OOP 3 — Polymorphism (Bagian 8)

Kesimpulan: Kenapa Disebut Polymorphism? 🏆

💡 Karena pemanggilan method-nya persis sama (h.bersuara();), tetapi perilaku / hasilnya berbeda sesuai objek yang sedang ditunjuk oleh h.

📊 Tabel Pemanggilan Polymorphism

Objek Method Dipanggil Output
Anjing() bersuara() Guk guk!
Kucing() bersuara() Meong!

Definisi Utama Polymorphism:

"Satu nama method (bersuara()), tetapi memiliki banyak bentuk perilaku tergantung objek yang memanggilnya."

🛡️ Pilar OOP 4 — Abstraction

Abstraction = Mengemudi Tanpa Tahu Mesin

🚗 Analogi: Mengendarai Mobil

⚙️⚙️
Panel tertutup — mesin tersembunyi
🚗

Kamu cukup injak pedal gas — gigi berputar di balik panel tanpa perlu kamu pahami. Itulah abstraction: detail rumit disembunyikan.

Penjelasan Teknis

  • abstract class mendefinisikan "kontrak" tanpa detail.
  • Method abstrak wajib diimplementasi child class.
  • Pengguna fokus pada apa, bukan bagaimana.
abstract class Kendaraan {
  void nyalakan(); // kontrak: detail disembunyikan
}

class Mobil extends Kendaraan {
  @override
  void nyalakan() => print('Mesin mobil menyala (brrm!)');
}

void main() {
  Kendaraan k = Mobil();
  k.nyalakan(); // user tak perlu tahu detail mesin
}
Terminal Output
Klik “Jalankan Kode” untuk melihat hasilnya ▸
🗺️ Hubungan Antar Konsep

Peta Konsep OOP

Semua bermula dari Class. Dari sana lahir Object, dan 4 pilar OOP menempel padanya.

CLASS (Blueprint) OBJECT (Instance) Encapsulation Abstraction Inheritance Property/Method Getter/Setter extends/super Polymorphism
📱 Konteks Nyata

OOP di Dalam Flutter

Flutter dibangun sepenuhnya di atas OOP. Setiap Widget adalah sebuah class!

Setiap Widget = Class

  • Text, Container, Column — semuanya class.
  • Kamu membuat widget baru dengan extends StatelessWidgetInheritance.
  • Method build() di-@overridePolymorphism.
  • State internal disembunyikan → Encapsulation.
// Widget Flutter adalah sebuah class!
class KartuMahasiswa extends StatelessWidget {
  final String nama;       // property
  const KartuMahasiswa(this.nama);

  @override                // polymorphism
  Widget build(BuildContext context) {
    return Text('Mahasiswa: $nama');
  }
}
Intinya Menguasai OOP = setengah jalan menuju mahir Flutter. 4 pilar tadi muncul di setiap layar yang kamu buat.
🚀 Mini Project — Bagian 1

Sistem Data Mahasiswa

Kita gabungkan semua konsep menjadi satu program nyata.

Fitur yang Dibangun

  • Tambah data mahasiswa baru.
  • Tampilkan seluruh daftar mahasiswa.
  • Update nilai / IPK mahasiswa.
  • Menerapkan: Class, Object, Constructor, Method, Encapsulation.

Alur Data

Input
💾Simpan
📋Tampil
✏️Update
🚀 Mini Project — Bagian 2

Kode Lengkap

Baca komentar // di tiap baris untuk memahami fungsinya.

// === Class blueprint untuk satu mahasiswa ===
class Mahasiswa {
  String nama;            // property: nama
  String nim;             // property: nomor induk
  double _nilai = 0;      // private (encapsulation)

  Mahasiswa(this.nama, this.nim);          // constructor

  double get nilai => _nilai;              // getter aman
  void setNilai(double n) {                // setter terkontrol
    if (n >= 0 && n <= 100) _nilai = n;    // validasi
  }

  void tampil() {                          // method
    print('$nim | $nama | nilai: $_nilai');
  }
}

// === Class pengelola daftar mahasiswa ===
class SistemAkademik {
  final List<Mahasiswa> _data = [];        // koleksi objek

  void tambah(Mahasiswa m) => _data.add(m);
  void tampilSemua() {
    print('=== DAFTAR MAHASISWA ===');
    for (var m in _data) m.tampil();       // polymorphism-ready
  }
}

void main() {
  var sistem = SistemAkademik();
  var a = Mahasiswa('Budi', '24001');
  var b = Mahasiswa('Sari', '24002');
  a.setNilai(88);
  b.setNilai(92);
  sistem.tambah(a);
  sistem.tambah(b);
  sistem.tampilSemua();
}
🚀 Mini Project — Bagian 3

Output & Demo Visual

Beginilah hasil saat program dijalankan di terminal:

dart run sistem_akademik.dart
🎯 Latihan 1

Class & Object Sederhana

Soal

Buat sebuah class Buku dengan property judul dan penulis, lalu buat 2 objek buku dan tampilkan datanya.

Langkah Pengerjaan

  1. Definisikan class Buku dengan dua property.
  2. Tambahkan constructor Buku(this.judul, this.penulis).
  3. Buat method info() yang mencetak judul & penulis.
  4. Di main(), buat 2 objek dan panggil info().
Contoh Output yang Diharapkan Laskar Pelangi — Andrea Hirata
Bumi — Tere Liye
🎯 Latihan 2

Inheritance & Method Override

Skenario

Sebuah kebun binatang punya banyak Hewan. Setiap hewan bisa bersuara(), tapi tiap jenis hewan bunyinya berbeda.

Struktur Class yang Harus Dibuat

  1. Class induk Hewan dengan method bersuara().
  2. Class Sapi extends Hewan → override jadi "Moo".
  3. Class Ayam extends Hewan → override jadi "Kukuruyuk".
  4. Buat List<Hewan> berisi keduanya, panggil bersuara() dalam loop.
Contoh Output yang Diharapkan Moo
Kukuruyuk
📋 Tugas Akhir BAB 3

Sistem Data Siswa (Mandiri)

Instruksi

Bangun program Sistem Data Siswa versimu sendiri yang dapat menyimpan dan menampilkan beberapa siswa beserta nilainya.

Spesifikasi Wajib

  • Minimal 2 class.
  • Menerapkan 1 inheritance (mis. Siswa & SiswaBeasiswa).
  • Menerapkan 1 encapsulation (nilai private + getter/setter).
  • Minimal 3 objek dibuat dan ditampilkan.

Rubrik Penilaian

KriteriaPoin
Struktur class benar30
Inheritance tepat25
Encapsulation tepat25
Program berjalan & output benar20

⏰ Deadline: ____ / ____ / ______  |  Kumpulkan file .dart beserta screenshot output.

🧠 Ringkasan

Recap BAB 3 — Klik Kartu untuk Membalik

🎉 Selamat!

Kamu Telah Menyelesaikan BAB 3

Kamu kini berpikir dalam bentuk objek — fondasi setiap aplikasi Flutter.

🔭 Selanjutnya — BAB 4

Widget & Layout Flutter: menerapkan OOP untuk membangun antarmuka aplikasi pertamamu yang bisa dilihat dan disentuh.

"Setiap programmer hebat pernah bingung dengan OOP. Kamu sudah melewatinya. Teruslah membangun!"

← → untuk navigasi