Enkapsulasi memang memiliki tujuan, tetapi juga dapat disalahgunakan atau disalahgunakan.
Pertimbangkan sesuatu seperti Android API yang memiliki kelas dengan lusinan (jika tidak ratusan) bidang. Mengekspos bidang-bidang yang konsumen API membuatnya sulit untuk dinavigasi dan menggunakan, juga memberikan pengguna gagasan palsu bahwa ia dapat melakukan apa pun yang ia inginkan dengan bidang-bidang yang mungkin bertentangan dengan bagaimana mereka seharusnya digunakan. Jadi enkapsulasi sangat bagus untuk pemeliharaan, kegunaan, keterbacaan, dan menghindari bug gila.
Di sisi lain, POD atau tipe data lama biasa, seperti struct dari C / C ++ di mana semua bidang bersifat publik dapat berguna juga. Memiliki getter / setter yang tidak berguna seperti yang dihasilkan oleh anotasi @ data di Lombok hanyalah cara untuk menjaga "pola enkapsulasi". Salah satu dari sedikit alasan kami melakukan pengambil / setter "tidak berguna" di Jawa adalah bahwa metode tersebut memberikan kontrak .
Di Jawa, Anda tidak bisa memiliki bidang dalam antarmuka, oleh karena itu Anda menggunakan getter dan setter untuk menentukan properti umum yang dimiliki semua pelaksana antarmuka itu. Dalam bahasa yang lebih baru seperti Kotlin atau C # kita melihat konsep properti sebagai bidang yang dapat Anda deklarasikan sebagai setter dan pengambil. Pada akhirnya, getter / setters yang tidak berguna lebih merupakan warisan yang harus dijalani oleh Java, kecuali Oracle menambahkan properti padanya. Kotlin, misalnya, yang merupakan bahasa JVM lain yang dikembangkan oleh JetBrains, memiliki kelas data yang pada dasarnya melakukan apa yang dilakukan oleh anotasi @ data di Lombok.
Juga ada beberapa contoh:
class DataClass
{
private int data;
public int getData() { return data; }
public void setData(int data) { this.data = data; }
}
Ini adalah kasus enkapsulasi yang buruk. Para pengambil dan penyetel secara efektif tidak berguna. Enkapsulasi banyak digunakan karena ini adalah standar dalam bahasa seperti Java. Tidak benar-benar membantu, selain menjaga konsistensi di seluruh basis kode.
class DataClass implements IDataInterface
{
private int data;
@Override public int getData() { return data; }
@Override public void setData(int data) { this.data = data; }
}
Ini adalah contoh enkapsulasi yang bagus. Enkapsulasi digunakan untuk menegakkan kontrak, dalam hal ini IDataInterface. Tujuan enkapsulasi dalam contoh ini adalah untuk membuat konsumen kelas ini menggunakan metode yang disediakan oleh antarmuka. Meskipun pengambil dan penyetel tidak melakukan apa pun yang mewah, kami sekarang telah mendefinisikan sifat umum antara DataClass dan pelaksana lainnya dari IDataInterface. Dengan demikian saya dapat memiliki metode seperti ini:
void doSomethingWithData(IDataInterface data) { data.setData(...); }
Sekarang, ketika berbicara tentang enkapsulasi saya pikir penting untuk juga mengatasi masalah sintaksis. Saya sering melihat orang mengeluh tentang sintaksis yang diperlukan untuk menegakkan enkapsulasi daripada enkapsulasi itu sendiri. Salah satu contoh yang muncul dalam pikiran adalah dari Casey Muratori (Anda dapat melihat kata-katanya di sini ).
Misalkan Anda memiliki kelas pemain yang menggunakan enkapsulasi dan ingin memindahkan posisinya dengan 1 unit. Kode akan terlihat seperti ini:
player.setPosX(player.getPosX() + 1);
Tanpa enkapsulasi akan terlihat seperti ini:
player.posX++;
Di sini ia berpendapat bahwa enkapsulasi mengarah ke lebih banyak mengetik tanpa manfaat tambahan dan ini dalam banyak kasus bisa benar, tetapi perhatikan sesuatu. Argumen itu menentang sintaksis, bukan enkapsulasi itu sendiri. Bahkan dalam bahasa seperti C yang tidak memiliki konsep enkapsulasi, Anda akan sering melihat variabel dalam struct yang dipraxif atau sufixed dengan '_' atau 'my' atau apa pun untuk menandakan bahwa mereka tidak boleh digunakan oleh pengguna API, seolah-olah mereka adalah pribadi.
Faktanya adalah enkapsulasi dapat membantu membuat kode lebih mudah dirawat dan mudah digunakan. Pertimbangkan kelas ini:
class VerticalList implements ...
{
private int posX;
private int posY;
... //other members
public void setPosition(int posX, int posY)
{
//change position and move all the objects in the list as well
}
}
Jika variabel bersifat publik dalam contoh ini, maka konsumen API ini akan bingung kapan harus menggunakan posX dan posY dan kapan harus menggunakan setPosition (). Dengan menyembunyikan detail itu, Anda membantu konsumen lebih baik menggunakan API Anda dengan cara yang intuitif.
Sintaksnya adalah batasan dalam banyak bahasa. Namun bahasa yang lebih baru menawarkan properti yang memberi kita sintaksis yang bagus dari anggota publice dan manfaat enkapsulasi. Anda akan menemukan properti di C #, Kotlin, bahkan di C ++ jika Anda menggunakan MSVC. di sini adalah contoh di Kotlin.
kelas VerticalList: ... {var posX: Int set (x) {field = x; ...} var posY: Int set (y) {field = y; ...}}
Di sini kita mencapai hal yang sama seperti pada contoh Java, tetapi kita dapat menggunakan posX dan posY seolah-olah mereka variabel publik. Ketika saya mencoba mengubah nilainya, isi set settter () akan dieksekusi.
Di Kotlin misalnya, ini akan menjadi setara dengan Java Bean dengan getter, setter, kode hash, sama dengan dan toString diimplementasikan:
data class DataClass(var data: Int)
Perhatikan bagaimana sintaks ini memungkinkan kita melakukan Java Bean dalam satu baris. Anda dengan benar memperhatikan masalah yang dimiliki bahasa seperti Java dalam mengimplementasikan enkapsulasi, tetapi itu adalah kesalahan Java bukan enkapsulasi itu sendiri.
Anda mengatakan bahwa Anda menggunakan @Data Lombok untuk menghasilkan getter dan setter. Perhatikan namanya, @ Data. Ini sebagian besar dimaksudkan untuk digunakan pada kelas data yang hanya menyimpan data dan dimaksudkan untuk serial dan deserialized. Pikirkan sesuatu seperti menyimpan file dari gim. Tetapi dalam skenario lain, seperti dengan elemen UI, Anda paling pasti menginginkan setter karena hanya mengubah nilai variabel mungkin tidak cukup untuk mendapatkan perilaku yang diharapkan.
"It will create getters, setters and setting constructors for all private fields."
- Cara Anda menjelaskan alat ini, kedengarannya seperti itu adalah mempertahankan enkapsulasi. (Setidaknya dalam pengertian model yang longgar, otomatis, dan agak anemia.) Jadi, apa sebenarnya masalahnya?