EDIT: Saya menjawab pertanyaan ini karena ada banyak orang yang belajar pemrograman menanyakan hal ini, dan sebagian besar jawabannya sangat kompeten secara teknis, tetapi mereka tidak mudah dimengerti jika Anda seorang pemula. Kami semua pemula, jadi saya pikir saya akan mencoba jawaban yang lebih ramah bagi pemula.
Dua yang utama adalah polimorfisme, dan validasi. Bahkan jika itu hanya struktur data yang bodoh.
Katakanlah kita memiliki kelas sederhana ini:
public class Bottle {
public int amountOfWaterMl;
public int capacityMl;
}
Kelas yang sangat sederhana yang menampung berapa banyak cairan di dalamnya, dan berapa kapasitasnya (dalam mililiter).
Apa yang terjadi ketika saya melakukannya:
Bottle bot = new Bottle();
bot.amountOfWaterMl = 1500;
bot.capacityMl = 1000;
Nah, Anda tidak akan berharap itu berhasil, bukan? Anda ingin ada semacam pemeriksaan kewarasan. Dan lebih buruknya, bagaimana jika saya tidak pernah menentukan kapasitas maksimum? Oh sayang, kami punya masalah.
Tapi ada masalah lain juga. Bagaimana jika botol hanya satu jenis wadah? Bagaimana jika kita memiliki beberapa wadah, semua dengan kapasitas dan jumlah cairan yang diisi? Jika kita bisa membuat antarmuka, kita bisa membiarkan sisa program kita menerima antarmuka itu, dan botol, jerigen dan segala macam hal hanya akan bekerja secara bergantian. Bukankah itu lebih baik? Karena metode permintaan antarmuka, ini juga merupakan hal yang baik.
Kami akan berakhir dengan sesuatu seperti:
public interface LiquidContainer {
public int getAmountMl();
public void setAmountMl(int amountMl);
public int getCapacityMl();
}
Bagus! Dan sekarang kita hanya mengganti Botol dengan ini:
public class Bottle extends LiquidContainer {
private int capacityMl;
private int amountFilledMl;
public Bottle(int capacityMl, int amountFilledMl) {
this.capacityMl = capacityMl;
this.amountFilledMl = amountFilledMl;
checkNotOverFlow();
}
public int getAmountMl() {
return amountFilledMl;
}
public void setAmountMl(int amountMl) {
this.amountFilled = amountMl;
checkNotOverFlow();
}
public int getCapacityMl() {
return capacityMl;
}
private void checkNotOverFlow() {
if(amountOfWaterMl > capacityMl) {
throw new BottleOverflowException();
}
}
Saya akan meninggalkan definisi BottleOverflowException sebagai latihan untuk pembaca.
Sekarang perhatikan betapa kuatnya ini. Kami dapat menangani semua jenis wadah dalam kode kami sekarang dengan menerima LiquidContainer, bukan Botol. Dan bagaimana botol-botol ini menangani hal-hal semacam ini bisa berbeda. Anda dapat memiliki botol yang menuliskan statusnya ke disk saat berubah, atau botol yang menghemat database SQL atau GNU tahu apa lagi.
Dan semua ini dapat memiliki cara berbeda untuk menangani berbagai waria. Botol hanya memeriksa dan jika meluap, ia melempar RuntimeException. Tapi itu mungkin hal yang salah untuk dilakukan. (Ada diskusi yang bermanfaat untuk dilakukan tentang penanganan kesalahan, tapi saya sengaja membuatnya sangat sederhana di sini. Orang-orang dalam komentar kemungkinan akan menunjukkan kekurangan dari pendekatan sederhana ini;;))
Dan ya, sepertinya kita beralih dari ide yang sangat sederhana untuk mendapatkan jawaban yang jauh lebih baik dengan cepat.
Harap dicatat juga bahwa Anda tidak dapat mengubah kapasitas botol. Sekarang diatur di atas batu. Anda bisa melakukan ini dengan int dengan menyatakannya final. Tetapi jika ini adalah daftar, Anda dapat mengosongkannya, menambahkan hal-hal baru ke dalamnya, dan seterusnya. Anda tidak dapat membatasi akses untuk menyentuh jeroan.
Ada juga hal ketiga yang tidak semua orang atasi: getter dan setter menggunakan panggilan metode. Itu berarti mereka terlihat seperti metode normal di tempat lain. Alih-alih memiliki sintaks khusus aneh untuk DTO dan yang lainnya, Anda memiliki hal yang sama di mana-mana.