Masukkan Password
69 Exercise Solution Chapter 6 OOP | Object Oriented Programming Chapter 6 Exercise Solution: Learn OOP
Kali ini saya akan menjelaskan isi tutorial kedua tersebut secara lebih detail, terutama karena video ini bukan hanya memberikan soal, tetapi juga memperlihatkan cara menyelesaikannya di Dart/VS Code.
Ada satu hal penting: di caption beberapa tipe data/penamaan terdengar kurang jelas karena hasil transkripsi otomatis. Saya akan menuliskan versi kode yang lebih rapi dan benar secara konsep, sambil menjelaskan maksud setiap bagian.
1. Class Laptop, Constructor, dan Object
Soal pertama:
Buat class
Laptopdengan propertyid,name, danram. Kemudian buat 3 object dan tampilkan semua detailnya.
A. Membuat class
Class adalah cetakan untuk membuat object.
class Laptop {
int id;
String name;
String ram;
Laptop(this.id, this.name, this.ram);
}
Di sini kita mempunyai:
Laptop
├── id
├── name
└── ram
Misalnya kita ingin membuat laptop HP:
Laptop laptop1 = Laptop(0, "HP", "4 GB");
Maka isinya:
id = 0
name = HP
ram = 4 GB
B. Constructor
Bagian ini:
Laptop(this.id, this.name, this.ram);
adalah constructor.
Constructor digunakan untuk memberikan nilai ketika object dibuat.
Tanpa constructor, kita mungkin harus melakukan:
var laptop1 = Laptop();
laptop1.id = 0;
laptop1.name = "HP";
laptop1.ram = "4 GB";
Dengan constructor, cukup:
var laptop1 = Laptop(0, "HP", "4 GB");
Jauh lebih singkat.
C. Membuat tiga object
var laptop1 = Laptop(0, "HP", "4 GB");
var laptop2 = Laptop(1, "HP", "8 GB");
var laptop3 = Laptop(2, "Dell", "16 GB");
Sekarang kita mempunyai tiga object:
laptop1 → HP → 4 GB
laptop2 → HP → 8 GB
laptop3 → Dell → 16 GB
Walaupun ketiganya dibuat dari class yang sama, masing-masing object memiliki data sendiri.
D. Mengambil data object
Untuk mengambil id:
laptop1.id
Untuk mengambil name:
laptop1.name
Untuk mengambil ram:
laptop1.ram
Contoh:
print("ID: ${laptop1.id}");
print("Name: ${laptop1.name}");
print("RAM: ${laptop1.ram}");
Program lengkap
class Laptop {
int id;
String name;
String ram;
Laptop(this.id, this.name, this.ram);
}
void main() {
var laptop1 = Laptop(0, "HP", "4 GB");
var laptop2 = Laptop(1, "HP", "8 GB");
var laptop3 = Laptop(2, "Dell", "16 GB");
print("Laptop 1");
print("ID: ${laptop1.id}");
print("Name: ${laptop1.name}");
print("RAM: ${laptop1.ram}");
print("\nLaptop 2");
print("ID: ${laptop2.id}");
print("Name: ${laptop2.name}");
print("RAM: ${laptop2.ram}");
print("\nLaptop 3");
print("ID: ${laptop3.id}");
print("Name: ${laptop3.name}");
print("RAM: ${laptop3.ram}");
}
2. Class House + Constructor + List
Soal kedua meminta:
Buat class
Housedenganid,name, danprice. Buat constructor. Buat 3 object, masukkan ke dalam List, kemudian print semuanya.
Ini sebenarnya menggabungkan beberapa konsep:
Class
↓
Constructor
↓
Object
↓
List
↓
Loop
↓
Print
A. Membuat class House
class House {
int id;
String name;
int price;
House(this.id, this.name, this.price);
}
Kita bisa membuat object:
var house1 = House(0, "House One", 200);
var house2 = House(1, "House Two", 300);
var house3 = House(2, "House Three", 500);
B. Membuat List
Sekarang kita punya tiga object.
Daripada menyimpan seperti ini:
house1
house2
house3
kita bisa memasukkannya ke sebuah List.
List<House> houses = [
house1,
house2,
house3,
];
Artinya:
housesadalah List yang berisi object-object bertipeHouse.
Secara sederhana:
houses
├── house1
├── house2
└── house3
C. Apa itu index?
Ini bagian yang sangat penting dari penjelasan video.
Dalam Dart, index List dimulai dari 0, bukan 1.
Misalnya:
List<String> names = [
"Andi",
"Budi",
"Citra"
];
Index-nya:
Index Data
0 Andi
1 Budi
2 Citra
Jadi:
names[0]
menghasilkan:
Andi
Sedangkan:
names[2]
menghasilkan:
Citra
D. length berbeda dengan index terakhir
Misalnya:
houses.length
hasilnya:
3
Karena ada 3 house.
Tetapi index terakhir adalah:
2
Karena index dimulai dari 0.
Jadi:
length = 3
index terakhir = 2
Secara umum:
index terakhir = length - 1
E. Menggunakan for loop
Video menggunakan:
for (int i = 0; i < houses.length; i++) {
...
}
Mari kita pecah:
int i = 0
Mulai dari index 0.
Kemudian:
i < houses.length
Selama i masih lebih kecil dari jumlah data.
Kemudian:
i++
Setelah satu putaran, i bertambah 1.
Jadinya:
i = 0
i = 1
i = 2
Ketika i = 3:
3 < 3
hasilnya false, sehingga loop berhenti.
F. Mengakses object dari List
Misalnya:
houses[i]
Kalau i = 0, berarti:
houses[0]
yaitu house pertama.
Untuk mengambil ID:
houses[i].id
Untuk nama:
houses[i].name
Untuk harga:
houses[i].price
Program lengkap
class House {
int id;
String name;
int price;
House(this.id, this.name, this.price);
}
void main() {
var house1 = House(0, "House One", 200);
var house2 = House(1, "House Two", 300);
var house3 = House(2, "House Three", 500);
List<House> houses = [
house1,
house2,
house3,
];
for (int i = 0; i < houses.length; i++) {
print("House ${i + 1}");
print("ID: ${houses[i].id}");
print("Name: ${houses[i].name}");
print("Price: ${houses[i].price}");
print("");
}
}
3. Enum Gender
Soal ketiga:
Buat enum untuk gender: male, female, dan others. Kemudian print semua nilainya.
Apa itu enum?
enum digunakan ketika kita mempunyai sekumpulan pilihan yang sudah ditentukan.
Contohnya:
enum Gender {
male,
female,
others
}
Berarti Gender mempunyai tiga nilai:
male
female
others
Gender.values
Untuk mendapatkan semua nilai enum:
Gender.values
Hasilnya berupa semua nilai:
Gender.male
Gender.female
Gender.others
Kalau ingin print satu per satu:
for (var gender in Gender.values) {
print(gender);
}
Atau pada Dart modern:
for (var gender in Gender.values) {
print(gender.name);
}
Output:
male
female
others
Program lengkap
enum Gender {
male,
female,
others
}
void main() {
for (var gender in Gender.values) {
print(gender.name);
}
}
Kapan enum berguna?
Misalnya kita mempunyai status:
enum Status {
pending,
approved,
rejected
}
Daripada menggunakan String sembarangan:
"pending"
"approved"
"abc"
kita dapat membatasi pilihan menggunakan enum.
4. Inheritance — Animal dan Cat
Ini salah satu konsep OOP yang sangat penting.
Soalnya:
Buat class
Animaldengan propertyid,name,color. Buat classCatyang extendsAnimal, lalu tambahkan propertysound.
Strukturnya:
Animal
/ | \
id name color
↓
Cat
|
sound
Jadi Cat mendapatkan property dari Animal.
A. Parent class
class Animal {
int id;
String name;
String color;
Animal(this.id, this.name, this.color);
}
Animal disebut parent/superclass.
B. Child class
class Cat extends Animal {
String sound;
Cat(int id, String name, String color, this.sound)
: super(id, name, color);
}
Perhatikan:
extends Animal
Artinya:
CatmewarisiAnimal.
C. Mengapa ada super?
Constructor Animal membutuhkan:
Animal(this.id, this.name, this.color);
Ketika membuat Cat, kita juga harus memberikan data tersebut kepada Animal.
Itulah fungsi:
super(id, name, color)
Jadi:
Cat constructor
↓
super(...)
↓
Animal constructor
D. Property sound
id, name, dan color berasal dari:
Animal
Sedangkan:
sound
ditambahkan khusus untuk:
Cat
Jadi object Cat mempunyai semuanya:
Cat
├── id
├── name
├── color
└── sound
E. Membuat object Cat
var cat = Cat(
0,
"Cat One",
"White",
"Meow",
);
Kemudian:
print("ID: ${cat.id}");
print("Name: ${cat.name}");
print("Color: ${cat.color}");
print("Sound: ${cat.sound}");
Program lengkap
class Animal {
int id;
String name;
String color;
Animal(this.id, this.name, this.color);
}
class Cat extends Animal {
String sound;
Cat(int id, String name, String color, this.sound)
: super(id, name, color);
}
void main() {
var cat = Cat(
0,
"Kitty",
"White",
"Meow",
);
print("ID: ${cat.id}");
print("Name: ${cat.name}");
print("Color: ${cat.color}");
print("Sound: ${cat.sound}");
}
5. Private Property + Getter & Setter
Ini bagian yang agak lebih sulit.
Soalnya:
Buat class
Cameradengan private propertiesid,brand,color, danprice. Kemudian buat getter dan setter untuk mendapatkan dan mengubah nilainya.
Konsep utamanya adalah encapsulation.
A. Apa maksud private?
Misalnya:
class Camera {
int? _id;
String? _brand;
String? _color;
double? _price;
}
Tanda:
_
di depan nama property menunjukkan bahwa property tersebut private terhadap library tempat ia didefinisikan.
Contohnya:
_id
_brand
_color
_price
B. Kenapa dibuat private?
Tujuannya adalah supaya data internal class tidak diakses sembarangan.
Bayangkan:
Camera
┌─────────────────────┐
│ _id │
│ _brand │
│ _color │
│ _price │
│ │
│ Getter → membaca │
│ Setter → mengubah │
└─────────────────────┘
Jadi getter dan setter menjadi semacam pintu untuk mengakses data.
C. Setter
Setter digunakan untuk mengubah nilai.
Contoh:
set id(int value) {
_id = value;
}
Kemudian dari luar class:
camera.id = 1;
Artinya setter akan menerima angka 1 dan menyimpannya ke:
_id
D. Getter
Getter digunakan untuk mengambil nilai.
int? get id {
return _id;
}
Kemudian:
print(camera.id);
akan mengambil nilai _id.
E. Contoh Camera
class Camera {
int? _id;
String? _brand;
String? _color;
double? _price;
set id(int value) {
_id = value;
}
int? get id {
return _id;
}
set brand(String value) {
_brand = value;
}
String? get brand {
return _brand;
}
set color(String value) {
_color = value;
}
String? get color {
return _color;
}
set price(double value) {
_price = value;
}
double? get price {
return _price;
}
}
F. Menggunakan Setter
Misalnya:
var camera = Camera();
camera.id = 1;
camera.brand = "Canon";
camera.color = "Black";
camera.price = 500;
Di sini kita mengisi data menggunakan setter.
G. Menggunakan Getter
Untuk membaca:
print(camera.id);
print(camera.brand);
print(camera.color);
print(camera.price);
Di sini kita menggunakan getter.
Program lengkap
class Camera {
int? _id;
String? _brand;
String? _color;
double? _price;
set id(int value) {
_id = value;
}
int? get id => _id;
set brand(String value) {
_brand = value;
}
String? get brand => _brand;
set color(String value) {
_color = value;
}
String? get color => _color;
set price(double value) {
_price = value;
}
double? get price => _price;
}
void main() {
var camera = Camera();
camera.id = 1;
camera.brand = "Canon";
camera.color = "Black";
camera.price = 500;
print("ID: ${camera.id}");
print("Brand: ${camera.brand}");
print("Color: ${camera.color}");
print("Price: ${camera.price}");
}
Kenapa menggunakan ?
Di video terlihat ada pembahasan tentang:
int?
String?
Tanda ? berarti nullable.
Contohnya:
int? id;
berarti id boleh mempunyai nilai integer atau null.
Misalnya:
id = 10
boleh.
id = null
juga boleh.
Ini berkaitan dengan null safety di Dart.
6. Interface + Abstract Class + Factory Constructor
Ini soal terakhir dan paling banyak konsepnya.
Soalnya meminta:
- Buat interface
Laptop - Buat method
turnOn - Buat
AppleLaptop - Implement
Laptop - Override
turnOn - Buat factory constructor
- Return object AppleLaptop
- Buat object menggunakan factory
- Panggil
turnOn
Kita pecah satu per satu.
A. Membuat abstract class
Dalam Dart, sebuah class dapat digunakan sebagai interface.
Contohnya:
abstract class Laptop {
void turnOn();
}
Kita mengatakan:
Setiap class yang mengimplementasikan
Laptopharus mempunyai methodturnOn().
Di sini:
void turnOn();
belum memiliki isi.
Kita hanya menentukan kontrak.
B. Membuat AppleLaptop
class AppleLaptop implements Laptop {
implements berarti:
AppleLaptop mengikuti aturan yang dibuat oleh Laptop.
Karena Laptop mempunyai:
void turnOn();
maka AppleLaptop wajib mempunyai:
void turnOn() {
...
}
C. Override
@override
void turnOn() {
print("Apple laptop is turned on");
}
@override menunjukkan bahwa kita sedang menyediakan implementasi dari method yang diwajibkan oleh interface/parent.
D. Constructor biasa
Video kemudian membuat constructor biasa/private untuk menjadi dasar factory.
Misalnya:
AppleLaptop._internal();
Constructor tersebut private karena diawali:
_
E. Factory Constructor
Kemudian:
factory AppleLaptop.second() {
return AppleLaptop._internal();
}
Ini adalah factory constructor.
Ketika kita melakukan:
var laptop = AppleLaptop.second();
factory tersebut mengembalikan object:
AppleLaptop._internal();
F. Mengapa menggunakan factory?
Constructor biasa secara langsung membuat instance.
Sedangkan factory constructor memberikan kita kontrol terhadap object yang dikembalikan.
Sederhananya:
AppleLaptop.second()
↓
factory
↓
AppleLaptop._internal()
↓
object
Factory berguna ketika proses pembuatan object membutuhkan logika khusus.
G. Program lengkap
abstract class Laptop {
void turnOn();
}
class AppleLaptop implements Laptop {
AppleLaptop._internal();
factory AppleLaptop.second() {
return AppleLaptop._internal();
}
@override
void turnOn() {
print("Apple laptop is turned on");
}
}
void main() {
var laptop = AppleLaptop.second();
laptop.turnOn();
}
Output:
Apple laptop is turned on
7. Memahami Factory dengan Analogi Sederhana
Bayangkan ada sebuah mesin pembuat laptop.
Kita tidak langsung mengambil laptop dari dalam mesin.
Kita mengatakan:
“Tolong berikan saya Apple Laptop.”
AppleLaptop.second()
Factory kemudian menentukan:
“Oke, saya akan membuat/mengembalikan object AppleLaptop.”
return AppleLaptop._internal();
Jadi factory bisa dibayangkan sebagai pabrik/pintu khusus untuk menghasilkan object.
8. Ringkasan Semua Soal
Sekarang kita rangkum keenam soal tersebut.
| Soal | Yang dipelajari |
|---|---|
| 1. Laptop | Class, Property, Object, Constructor |
| 2. House | Class, Constructor, List, Index, Loop |
| 3. Gender | Enum |
| 4. Animal & Cat | Inheritance, extends, super |
| 5. Camera | Encapsulation, Private, Getter, Setter |
| 6. AppleLaptop | Abstract class, Interface, implements, Override, Factory |
9. Hubungan Konsepnya
Kalau kamu masih bingung bagaimana semuanya saling berhubungan, bayangkan seperti ini:
OOP DART
│
┌────────────┴────────────┐
│ │
CLASS OBJECT
│ │
│ hasil dari class
│
CONSTRUCTOR
│
mengisi data
│
┌─────┴──────┐
│ │
Inheritance Encapsulation
│ │
extends private _
│ │
super getter/setter
│
└──────────────┐
│
ABSTRACT
/ INTERFACE
│
implements
│
override
│
factory constructor
10. Bagian yang Wajib Kamu Pahami
Kalau ini untuk belajar atau persiapan ujian, menurut saya jangan menghafal keenam program tersebut secara mentah. Pahami fungsi masing-masing keyword.
class
Membuat cetakan.
class Laptop {}
new object
Membuat benda dari cetakan.
var laptop = Laptop();
constructor
Memberikan nilai saat object dibuat.
Laptop(this.id, this.name);
extends
Mewarisi class.
class Cat extends Animal {}
super
Memanggil constructor/anggota dari parent.
super(id, name, color);
enum
Membuat pilihan yang sudah ditentukan.
enum Gender {
male,
female,
others
}
_
Menandai identifier sebagai private terhadap library.
int? _id;
get
Mengambil/membaca data.
int? get id => _id;
set
Mengubah data.
set id(int value) {
_id = value;
}
abstract
Membuat class abstrak yang dapat menjadi dasar/kontrak.
abstract class Laptop {
void turnOn();
}
implements
Mengikuti kontrak/interface.
class AppleLaptop implements Laptop {}
@override
Memberikan implementasi untuk method yang diwarisi/diwajibkan.
@override
void turnOn() {}
factory
Constructor khusus yang dapat mengontrol object yang dikembalikan.
factory AppleLaptop.second() {
return AppleLaptop._internal();
}
Inti terbesar dari Chapter 6
Kalau harus dibuat sangat sederhana, ingat kalimat berikut:
Class adalah cetakan, object adalah hasil cetakan, constructor mengisi data saat object dibuat, inheritance memungkinkan class mewarisi class lain, getter/setter mengatur akses data, enum membatasi pilihan, interface menentukan aturan, dan factory constructor mengontrol object yang dikembalikan.
Dengan memahami kalimat tersebut, keenam latihan di video akan jauh lebih mudah dipahami daripada sekadar menghafalkan kode.
Saya juga bisa membuat gambar/diagram visual alur keenam konsep OOP ini supaya hubungan class → object → constructor → inheritance → getter/setter → interface → factory lebih mudah diingat.