Masukkan Password
56 6.5 What is Encapsulation in OOP | Hide Data with Encapsulation in OOP | Learn OOP | Dart Course
Mari kita bahas Encapsulation pada Dart dengan bahasa yang sederhana dan bertahap.
1. Apa itu Encapsulation?
Encapsulation (enkapsulasi) adalah salah satu konsep penting dalam OOP (Object-Oriented Programming).
Secara sederhana:
Encapsulation adalah proses menyembunyikan data tertentu dan mengatur bagaimana data tersebut boleh diakses atau diubah.
Bayangkan sebuah brankas:
- Isi brankas = data
- Pintu brankas = perlindungan
- Kunci atau mekanisme akses = method/fungsi yang mengatur akses
Orang tidak bisa langsung mengambil isi brankas sesuka hati. Mereka harus menggunakan cara yang telah disediakan.
Begitu juga dalam program:
Data penting
↓
Disembunyikan/dilindungi
↓
Diakses melalui method yang kita sediakan
2. Mengapa Encapsulation diperlukan?
Misalnya kita memiliki data mahasiswa:
- Nama
- Nomor induk
- Nilai
Tanpa encapsulation, program lain bisa langsung mengubah semuanya:
student.name = "Budi";
student.marks = -100;
Masalahnya, nilai -100 mungkin tidak valid.
Dengan encapsulation, kita dapat mengontrol perubahan data:
Program lain
↓
meminta mengubah nilai
↓
Method melakukan pengecekan
↓
Jika valid → data diubah
Jika tidak valid → ditolak
Jadi, encapsulation membantu:
- Melindungi data
- Mencegah perubahan sembarangan
- Mengontrol akses ke data
- Membuat program lebih terstruktur
- Mempermudah perawatan program
3. Konsep private di Dart
Dalam Dart, kita dapat membuat member menjadi private dengan menambahkan underscore (_) di depan namanya.
Contoh:
String _name;
Variabel _name bersifat private terhadap library Dart.
Demikian juga function:
void _display() {
print("Hello");
}
Function tersebut juga private terhadap library.
4. Contoh dasar
Misalnya kita membuat class Student:
class Student {
String name;
String roll;
int marks;
}
Jika variabel tersebut tidak diawali underscore, variabel dapat diakses dari file/library lain:
student.name;
student.roll;
student.marks;
Artinya, data bersifat terbuka.
Sekarang kita ubah:
class Student {
String _name;
String _roll;
int _marks;
}
Sekarang kita memiliki:
_name_roll_marks
Ketiga data tersebut dibuat private.
Secara konsep:
Student
├── _name → private
├── _roll → private
└── _marks → private
Program dari luar library tidak seharusnya mengakses data tersebut secara langsung.
5. Menggunakan Constructor untuk mengisi data private
Walaupun variabel private tidak dapat diakses langsung dari luar, kita tetap dapat memberikan nilainya melalui constructor.
Contoh yang lebih lengkap:
class Student {
final String _name;
final String _roll;
final int _marks;
Student(this._name, this._roll, this._marks);
}
Kemudian:
void main() {
Student student = Student(
"Ahmad",
"101",
85,
);
}
Alurnya:
main()
↓
membuat object Student
↓
Student("Ahmad", "101", 85)
↓
Constructor menerima data
↓
_name = "Ahmad"
_roll = "101"
_marks = 85
Data berhasil dimasukkan, meskipun variabelnya private.
6. Bagaimana cara menampilkan data private?
Karena data private tidak ingin kita akses secara langsung, kita bisa menyediakan method publik.
Contoh:
class Student {
final String _name;
final String _roll;
final int _marks;
Student(this._name, this._roll, this._marks);
void display() {
print("Name: $_name");
print("Roll Number: $_roll");
print("Marks: $_marks");
}
}
Di main():
void main() {
Student student = Student(
"Ahmad",
"101",
85,
);
student.display();
}
Output:
Name: Ahmad
Roll Number: 101
Marks: 85
Perhatikan perbedaannya:
student._name;
Data private tidak digunakan langsung dari luar.
Sebagai gantinya:
student.display();
Method display() menjadi pintu resmi untuk mengakses data.
Ilustrasinya:
Student Class
┌─────────────────────────┐
│ _name │ ← private
│ _roll │ ← private
│ _marks │ ← private
│ │
│ display() │ ← public
└─────────────────────────┘
↑
│
main() menggunakan
method display()
Inilah ide utama encapsulation.
7. Membuat setter sendiri
Video juga menjelaskan bahwa kita dapat menggunakan function untuk mengubah data private.
Contoh:
class Student {
late String _name;
void setName(String name) {
_name = name;
}
void printName() {
print(_name);
}
}
Kemudian:
void main() {
Student student = Student();
student.setName("Ahmad");
student.printName();
}
Output:
Ahmad
Alurnya:
student.setName("Ahmad")
↓
setName() menerima "Ahmad"
↓
_name = "Ahmad"
↓
Data disimpan dalam variabel private
Kemudian:
student.printName()
↓
printName() mengakses _name
↓
Menampilkan Ahmad
8. Keuntungan menggunakan method untuk mengubah data
Keuntungan sebenarnya baru terlihat ketika kita ingin melakukan validasi.
Misalnya nilai mahasiswa tidak boleh kurang dari 0 atau lebih dari 100.
class Student {
late int _marks;
void setMarks(int marks) {
if (marks >= 0 && marks <= 100) {
_marks = marks;
} else {
print("Marks must be between 0 and 100");
}
}
void displayMarks() {
print("Marks: $_marks");
}
}
Penggunaan:
void main() {
Student student = Student();
student.setMarks(85);
student.displayMarks();
}
Output:
Marks: 85
Tetapi jika:
student.setMarks(150);
Maka:
Marks must be between 0 and 100
Inilah salah satu alasan terbesar kita menggunakan encapsulation.
Tanpa encapsulation:
student.marks = 150;
Data langsung berubah tanpa pemeriksaan.
Dengan encapsulation:
Program ingin mengubah nilai
↓
setMarks()
↓
Periksa validitas
↙ ↘
Valid Tidak valid
↓ ↓
Simpan Tolak data
9. Contoh dengan Getter dan Setter
Dalam Dart, cara yang lebih umum dan rapi adalah menggunakan getter dan setter.
Contoh:
class Student {
String _name = "";
String get name {
return _name;
}
set name(String value) {
if (value.isNotEmpty) {
_name = value;
}
}
}
Penggunaan:
void main() {
Student student = Student();
student.name = "Ahmad";
print(student.name);
}
Walaupun terlihat seperti kita langsung menggunakan variabel:
student.name = "Ahmad";
sebenarnya Dart menjalankan setter:
set name(String value)
Sedangkan:
print(student.name);
menjalankan getter:
String get name
Alurnya:
student.name = "Ahmad"
↓
Setter
↓
Pengecekan/validasi
↓
_name = "Ahmad"
Dan:
student.name
↓
Getter
↓
return _name
Ini adalah penerapan encapsulation yang sangat umum dalam OOP.
10. Private pada Dart dan konsep Library
Ini bagian penting yang perlu diperjelas dari penjelasan video.
Di Dart, underscore (_) membuat sebuah member bersifat library-private, bukan sekadar “private terhadap class”.
Contoh:
File student.dart
class Student {
String _name = "Ahmad";
}
Jika file tersebut diakses sebagai library berbeda, _name tidak dapat diakses secara langsung.
Misalnya:
File main.dart
import 'student.dart';
void main() {
Student student = Student();
print(student._name); // Tidak boleh dari library lain
}
Namun ada nuansa penting:
Private di Dart terkait dengan library, bukan secara mutlak hanya dengan class.
Jadi penjelasan sederhana dalam video bahwa underscore membuat variabel “private” benar untuk penggunaan sehari-hari, tetapi secara teknis Dart menggunakan konsep library privacy.
11. Public vs Private
Mari kita bandingkan.
Public
class Student {
String name = "Ahmad";
void display() {
print(name);
}
}
Dari luar:
student.name;
student.display();
Dapat diakses.
Private
class Student {
String _name = "Ahmad";
void _display() {
print(_name);
}
}
Member yang diawali _ bersifat private terhadap library.
Secara sederhana:
| Member | Akses |
|---|---|
name | Public |
display() | Public |
_name | Private/library-private |
_display() | Private/library-private |
12. Contoh lengkap Encapsulation
Berikut contoh yang menggabungkan semuanya:
class Student {
String _name = "";
int _age = 0;
double _marks = 0;
void setName(String name) {
if (name.isNotEmpty) {
_name = name;
}
}
void setAge(int age) {
if (age > 0) {
_age = age;
} else {
print("Age must be greater than 0");
}
}
void setMarks(double marks) {
if (marks >= 0 && marks <= 100) {
_marks = marks;
} else {
print("Marks must be between 0 and 100");
}
}
void display() {
print("Name: $_name");
print("Age: $_age");
print("Marks: $_marks");
}
}
void main() {
Student student = Student();
student.setName("Ahmad");
student.setAge(20);
student.setMarks(85);
student.display();
}
Output:
Name: Ahmad
Age: 20
Marks: 85.0
Struktur program:
main()
│
├── Student student = Student()
│
├── setName("Ahmad")
│ ↓
│ _name
│
├── setAge(20)
│ ↓
│ _age
│
├── setMarks(85)
│ ↓
│ Validasi
│ ↓
│ _marks
│
└── display()
↓
Menampilkan data
13. Hubungan Encapsulation dengan Constructor
Kita juga dapat menggabungkan encapsulation dengan constructor.
class Student {
final String _name;
final int _age;
Student(String name, int age)
: _name = name,
_age = age;
void display() {
print("Name: $_name");
print("Age: $_age");
}
}
Penggunaan:
void main() {
Student student = Student("Ahmad", 20);
student.display();
}
Dengan final, nilai hanya diinisialisasi satu kali.
Kita juga bisa menggunakan shortcut:
class Student {
final String _name;
final int _age;
Student(this._name, this._age);
void display() {
print("Name: $_name");
print("Age: $_age");
}
}
Kesimpulan
Encapsulation berarti membungkus data dan method dalam class serta mengontrol akses terhadap data tersebut.
Hal-hal penting yang perlu diingat:
- Encapsulation adalah salah satu konsep utama OOP.
- Tujuannya adalah melindungi dan mengontrol akses data.
- Di Dart, nama yang diawali
_bersifat library-private. - Data private sebaiknya diakses melalui method, getter, atau setter yang disediakan.
- Method dapat digunakan untuk melakukan validasi sebelum data diubah.
- Encapsulation membuat kode lebih aman, rapi, dan mudah dikembangkan.
Gambaran paling sederhananya:
Tanpa Encapsulation:
Program luar ─────────────→ Data
langsung mengubah
Dengan Encapsulation:
Program luar
↓
Getter / Setter / Method
↓
Validasi dan aturan
↓
Data private
Jadi inti dari encapsulation adalah:
Jangan biarkan semua bagian program bebas mengubah data secara langsung. Sembunyikan data yang perlu dilindungi dan sediakan cara yang terkontrol untuk mengaksesnya.