Masukkan Password
57 6.6 What are Getter and Setter in OOP | Learn OOP in Dart Programming | Learn Dart | Dart Course
Materi kali ini sangat penting karena merupakan kelanjutan langsung dari encapsulation. Kalau sebelumnya kita belajar bagaimana menyembunyikan data dengan _, sekarang kita belajar:
- bagaimana membaca data private → getter
- bagaimana mengubah data private → setter
Saya akan jelaskan dari dasar supaya hubungan antara private property → getter → setter benar-benar jelas.
1. Apa itu Getter dan Setter?
Secara sederhana:
Getter digunakan untuk mengambil/membaca nilai property.
Setter digunakan untuk memberikan/mengubah nilai property.
Misalnya kita punya:
class Person {
String _name = "";
int _age = 0;
}
_name dan _age adalah private.
Dari luar class/library, kita tidak ingin mengaksesnya secara langsung.
Maka kita menyediakan:
Getter
↓
READ / membaca data
Setter
↓
WRITE / mengubah data
Gambaran sederhananya:
Person
┌────────────────────┐
│ _name │
│ _age │
│ │
│ getter → baca │
│ setter → ubah │
└────────────────────┘
↑
│
Program luar
2. Hubungan Getter/Setter dengan Encapsulation
Pada materi sebelumnya kita punya:
class Person {
String _name = "";
int _age = 0;
}
Kenapa menggunakan _?
Karena kita ingin menyembunyikan data tersebut.
Masalahnya:
Kalau datanya private, bagaimana cara kita membaca dan mengubahnya?
Jawabannya:
Getter dan Setter.
Jadi hubungan materinya seperti ini:
Encapsulation
↓
Sembunyikan data
↓
Data dibuat private dengan _
↓
Butuh akses yang terkontrol
↓
┌───────────────┐
│ Getter │ → membaca
│ Setter │ → mengubah
└───────────────┘
3. Getter = Mengambil/Membaca Nilai
Getter digunakan ketika kita ingin mendapatkan nilai dari property private.
Misalnya:
class Person {
String _name = "";
String get name {
return _name;
}
}
Perhatikan bagian ini:
String get name
Ini adalah getter.
Mari kita pecah:
String
↓
return type
get
↓
keyword getter
name
↓
nama getter
Kemudian:
return _name;
artinya getter mengembalikan nilai dari _name.
4. Cara Menggunakan Getter
Misalnya:
class Person {
String _name = "";
String get name {
return _name;
}
}
Kemudian:
void main() {
Person person = Person();
print(person.name);
}
Yang menarik adalah kita menulis:
person.name
bukan:
person.name()
Kenapa?
Karena getter digunakan seperti property, walaupun di belakang layar dia sebenarnya menjalankan kode.
Jadi:
print(person.name);
secara konsep:
person.name
↓
getter name
↓
return _name
↓
print hasilnya
5. Getter Bukan Function Biasa
Ini perbedaan penting.
Function biasa:
String getName() {
return _name;
}
Pemakaiannya:
person.getName();
Ada tanda:
()
Karena getName() adalah function biasa.
Sedangkan getter:
String get name {
return _name;
}
Pemakaiannya:
person.name;
Tidak ada ().
Jadi:
| Function biasa | Getter |
|---|---|
getName() | name |
person.getName() | person.name |
| Dipanggil sebagai function | Dipakai seperti property |
6. Setter = Mengubah/Mengisi Nilai
Sekarang kita ingin mengubah _name.
Kita bisa membuat setter:
set name(String name) {
_name = name;
}
Perhatikan:
set name
adalah setter.
Kemudian:
String name
adalah nilai yang diterima setter.
Dan:
_name = name;
berarti nilai tersebut disimpan ke property private _name.
7. Cara Menggunakan Setter
Misalnya:
class Person {
String _name = "";
set name(String name) {
_name = name;
}
}
Kemudian:
void main() {
Person person = Person();
person.name = "Budi";
}
Ini mungkin terlihat aneh bagi pemula.
Kita punya:
set name(String name)
yang sebenarnya seperti function.
Tetapi saat dipakai:
person.name = "Budi";
tidak menggunakan ().
Jadi bukan:
person.name("Budi"); // ❌
Melainkan:
person.name = "Budi"; // ✅
8. Kenapa Setter Terlihat Seperti Variabel?
Ini salah satu keunikan getter dan setter.
Misalnya kita menulis:
person.name = "Budi";
Kelihatannya seperti kita sedang memberikan nilai langsung ke property.
Tetapi sebenarnya Dart menjalankan setter:
set name(String value) {
_name = value;
}
Secara konsep:
person.name = "Budi"
↓
Setter name dipanggil
↓
value = "Budi"
↓
_name = "Budi"
Jadi setter memberi kita interface yang terlihat seperti property, tetapi kita tetap bisa menjalankan logic di dalamnya.
9. Contoh Getter dan Setter Lengkap
Mari kita buat class Person:
class Person {
String _name = "";
int _age = 0;
// Setter
set name(String name) {
_name = name;
}
set age(int age) {
_age = age;
}
// Getter
String get name {
return _name;
}
int get age {
return _age;
}
}
Kemudian:
void main() {
Person person = Person();
person.name = "Budi";
person.age = 20;
print(person.name);
print(person.age);
}
Output:
Budi
20
10. Perhatikan Alurnya
Ketika kita menulis:
person.name = "Budi";
yang terjadi:
person.name = "Budi"
↓
setter name
↓
_name = "Budi"
Kemudian ketika:
print(person.name);
yang terjadi:
person.name
↓
getter name
↓
return _name
↓
"Budi"
↓
print()
Jadi:
Person
│
┌───────┴───────┐
↓ ↓
Setter Getter
↓ ↑
WRITE READ
↓ ↑
_name ←──────────┘
11. Kenapa Tidak Langsung Saja Menggunakan Property Public?
Pertanyaan bagus.
Kenapa tidak:
class Person {
String name = "";
}
Kemudian:
person.name = "Budi";
print(person.name);
Selesai?
Bisa.
Tetapi masalahnya adalah kita kehilangan kontrol.
Misalnya umur tidak boleh negatif.
Kalau property public:
person.age = -100;
bisa saja dilakukan.
Dengan setter kita bisa membuat aturan:
set age(int age) {
if (age >= 0) {
_age = age;
} else {
print("Age tidak boleh negatif");
}
}
Sekarang:
person.age = -100;
akan ditolak.
12. Ini Kekuatan Sebenarnya Setter
Misalnya kita punya nilai ujian.
Nilai harus berada antara 0 sampai 100.
class Student {
double _marks = 0;
set marks(double value) {
if (value >= 0 && value <= 100) {
_marks = value;
} else {
print("Nilai harus antara 0 dan 100");
}
}
double get marks {
return _marks;
}
}
Penggunaan:
void main() {
Student student = Student();
student.marks = 85;
print(student.marks);
student.marks = 150;
print(student.marks);
}
Hasil:
85.0
Nilai harus antara 0 dan 100
85.0
Perhatikan:
student.marks = 150;
tidak langsung mengubah _marks.
Setter memeriksa dulu:
150
↓
Apakah 0 <= 150 <= 100?
↓
Tidak
↓
Tolak
Inilah yang dimaksud controlled access.
13. Getter Juga Bisa Memiliki Logic
Getter tidak harus hanya:
return _name;
Kita juga bisa melakukan perhitungan.
Contoh:
class Rectangle {
double _width = 0;
double _height = 0;
set width(double value) {
_width = value;
}
set height(double value) {
_height = value;
}
double get area {
return _width * _height;
}
}
Penggunaan:
void main() {
Rectangle rectangle = Rectangle();
rectangle.width = 10;
rectangle.height = 5;
print(rectangle.area);
}
Output:
50.0
Menariknya, area bukan property yang kita simpan secara langsung.
Tidak ada:
double _area;
Tetapi getter menghitungnya:
double get area {
return _width * _height;
}
Jadi getter bisa digunakan untuk computed property.
14. Getter dengan Arrow Function
Kalau getter hanya memiliki satu expression, kita bisa menggunakan arrow syntax.
Dari:
String get name {
return _name;
}
menjadi:
String get name => _name;
Artinya sama.
Begitu juga:
int get age => _age;
Jadi:
class Person {
String _name = "";
int _age = 0;
set name(String name) => _name = name;
set age(int age) => _age = age;
String get name => _name;
int get age => _age;
}
Lebih ringkas.
15. Kenapa Setter Tidak Memiliki Return Type?
Caption mengatakan setter tidak memiliki return type.
Benar.
Setter:
set name(String value) {
_name = value;
}
Bukan:
void set name(String value) // ❌
dan bukan:
String set name(String value) // ❌
Sintaks setter memang:
set namaSetter(Tipe parameter) {
// ...
}
Setter digunakan untuk memberikan nilai, bukan mengembalikan nilai.
16. Getter Harus Memiliki Return Type
Getter biasanya memiliki return type.
Misalnya _name bertipe String:
String get name => _name;
Maka getter-nya String.
Kalau _age bertipe int:
int get age => _age;
Maka getter-nya int.
Contoh:
_name → String
↓
getter → String
_age → int
↓
getter → int
17. Bagaimana dengan this?
Caption juga menjelaskan this.
Misalnya:
class Person {
String _name = "";
set name(String name) {
_name = name;
}
}
Di sini kita tidak perlu:
this._name = name;
karena nama field dan parameter berbeda:
field → _name
parameter → name
Tidak membingungkan.
18. Kapan this Dibutuhkan?
Misalnya kita menulis:
class Person {
String name = "";
Person(String name) {
this.name = name;
}
}
Di sini ada dua name:
this.name
↑
field milik object
name
↑
parameter constructor
Maka this digunakan untuk membedakannya.
Tetapi pada:
class Person {
String _name = "";
set name(String name) {
_name = name;
}
}
sudah jelas:
_name → field
name → parameter
Sehingga this tidak diperlukan.
19. Getter + Setter = Read + Write
Cara paling mudah mengingatnya:
GETTER
↓
GET
↓
ambil nilai
↓
READ
SETTER
↓
SET
↓
berikan nilai
↓
WRITE
Atau:
Getter → baca
Setter → ubah
Misalnya:
person.name
→ getter
Sedangkan:
person.name = "Budi";
→ setter
20. Private Property + Getter + Setter
Sekarang kita bisa melihat pola lengkap encapsulation:
class Person {
String _name = "";
int _age = 0;
// Setter
set name(String value) {
_name = value;
}
set age(int value) {
_age = value;
}
// Getter
String get name {
return _name;
}
int get age {
return _age;
}
}
Dari luar:
Person person = Person();
person.name = "Budi"; // setter
person.age = 20; // setter
print(person.name); // getter
print(person.age); // getter
Data aslinya:
_name
_age
tetap tersembunyi.
Yang terlihat dari luar:
name
age
melalui getter/setter.
21. Kenapa Ini Disebut Encapsulation?
Karena data dan logic dibungkus dalam class.
Contohnya:
Person
┌─────────────────────────────┐
│ │
│ PRIVATE DATA │
│ _name │
│ _age │
│ │
│ PUBLIC INTERFACE │
│ name getter │
│ name setter │
│ age getter │
│ age setter │
│ │
└─────────────────────────────┘
Program luar tidak perlu tahu bagaimana data sebenarnya disimpan.
Program luar cukup tahu:
person.name
dan:
person.name = "Budi";
Ini membuat bagian dalam class bisa diubah tanpa harus mengubah cara class digunakan dari luar.
22. Getter Tidak Harus Selalu Memiliki Setter
Ini juga penting.
Kita tidak wajib membuat getter dan setter berpasangan.
Misalnya kita ingin data hanya bisa dibaca dari luar:
class Person {
final String _id;
Person(this._id);
String get id => _id;
}
Dari luar:
print(person.id); // ✅
Tetapi:
person.id = "123"; // ❌
Kenapa?
Karena kita hanya menyediakan getter.
Jadi:
Getter saja
↓
READ ONLY
Ini sangat berguna untuk data yang tidak boleh diubah dari luar.
23. Setter Tidak Harus Memiliki Getter
Sebaliknya, kita juga bisa memiliki setter tanpa getter.
Misalnya program hanya boleh memberikan password, tetapi tidak boleh membaca password tersebut secara langsung:
class Account {
String _password = "";
set password(String value) {
_password = value;
}
}
Kita bisa:
account.password = "rahasia";
tetapi tidak menyediakan:
account.password
untuk membaca kembali password.
Ini contoh konsep write-only interface.
24. Getter/Setter vs Method Biasa
Bandingkan:
Method biasa
void setName(String name) {
_name = name;
}
String getName() {
return _name;
}
Penggunaan:
person.setName("Budi");
print(person.getName());
Getter/Setter
set name(String name) {
_name = name;
}
String get name {
return _name;
}
Penggunaan:
person.name = "Budi";
print(person.name);
Getter/setter memberikan interface yang terasa seperti property.
25. Contoh yang Lebih Realistis
Misalnya kita membuat class BankAccount.
Kita tidak ingin balance bisa diubah sembarangan.
class BankAccount {
double _balance = 0;
double get balance {
return _balance;
}
void deposit(double amount) {
if (amount > 0) {
_balance += amount;
}
}
void withdraw(double amount) {
if (amount > 0 && amount <= _balance) {
_balance -= amount;
}
}
}
Perhatikan kita tidak membuat setter untuk balance.
Kenapa?
Kita tidak ingin orang melakukan:
account.balance = 100000000;
Lebih aman jika saldo hanya bisa berubah melalui:
account.deposit(50000);
atau:
account.withdraw(20000);
Jadi encapsulation memungkinkan kita menentukan aturan bagaimana data boleh berubah.
26. Ini Lebih Bagus daripada Setter untuk Semua Data
Jangan menganggap:
“Kalau ada private field, pasti harus dibuat getter dan setter.”
Tidak selalu.
Misalnya:
class BankAccount {
double _balance = 0;
double get balance => _balance;
void deposit(double amount) {
if (amount > 0) {
_balance += amount;
}
}
}
Kita hanya menyediakan getter.
Tidak ada:
set balance(...)
Karena perubahan saldo harus melalui aturan deposit() dan withdraw().
Ini justru merupakan encapsulation yang lebih baik.
27. Ringkasan Syntax
Property private
String _name = "";
Setter
set name(String value) {
_name = value;
}
Getter
String get name {
return _name;
}
Setter arrow
set name(String value) => _name = value;
Getter arrow
String get name => _name;
Penggunaan setter
person.name = "Budi";
Penggunaan getter
print(person.name);
28. Pola yang Harus Kamu Hafalkan
Kalau masih bingung, cukup hafalkan pola ini:
class Person {
String _name = "";
// SETTER
set name(String value) {
_name = value;
}
// GETTER
String get name {
return _name;
}
}
Lalu:
Person person = Person();
person.name = "Budi"; // SET
print(person.name); // GET
Secara mental:
person.name = "Budi"
↓
SETTER
↓
_name = "Budi"
person.name
↓
GETTER
↓
return _name
29. Kesimpulan Besar
Materi ini sebenarnya merupakan kelanjutan yang sangat logis:
CLASS & OBJECT
↓
ENCAPSULATION
↓
sembunyikan data
↓
private field (_name)
↓
bagaimana mengaksesnya?
↓
┌───────────────────┐
│ Getter → membaca │
│ Setter → mengubah │
└───────────────────┘
Ingat tiga kata ini:
Private → Getter → Setter
- Private → menyembunyikan/melindungi data.
- Getter → memberikan akses baca.
- Setter → memberikan akses ubah/tulis.
Dan yang paling penting:
person.name
→ Getter
person.name = "Budi";
→ Setter
Sedangkan:
person.getName()
dan:
person.setName("Budi")
adalah method biasa, bukan getter/setter.
Jadi kalau kamu sudah memahami:
class → object → constructor → named constructor → const constructor → encapsulation → getter/setter,
kamu sebenarnya sudah mulai melihat bagaimana sebuah class Dart dirancang supaya data di dalamnya tidak asal bisa diakses dan diubah oleh bagian program lain.