Itu tergantung dari arti sebenarnya dari a
, b
dan getProduct
.
Tujuan getter adalah untuk dapat mengubah implementasi aktual sambil menjaga antarmuka objek tetap sama. Misalnya, jika suatu hari, getA
menjadi return a + 1;
, perubahan dilokalkan ke pengambil.
Kasus skenario nyata terkadang lebih rumit daripada bidang dukungan konstan yang ditetapkan melalui konstruktor yang terkait dengan pengambil. Misalnya, nilai bidang dapat dihitung atau dimuat dari database dalam versi asli kode. Di versi berikutnya, caching dapat ditambahkan untuk mengoptimalkan kinerja. Jika getProduct
terus menggunakan versi yang dihitung, itu tidak akan mendapat manfaat dari caching (atau pengelola akan melakukan perubahan yang sama dua kali).
Jika masuk akal untuk getProduct
digunakan a
dan b
secara langsung, gunakan itu. Kalau tidak, gunakan getter untuk mencegah masalah pemeliharaan nanti.
Contoh di mana seseorang akan menggunakan getter:
class Product {
public:
Product(ProductId id) : {
price = Money.fromCents(
data.findProductById(id).price,
environment.currentCurrency
)
}
Money getPrice() {
return price;
}
Money getPriceWithRebate() {
return getPrice().applyRebate(rebate); // ← Using a getter instead of a field.
}
private:
Money price;
}
Sementara untuk saat ini, pengambil tidak mengandung logika bisnis, tidak dikecualikan bahwa logika dalam konstruktor akan dimigrasikan ke pengambil untuk menghindari melakukan pekerjaan basis data saat menginisialisasi objek:
class Product {
public:
Product(ProductId id) : id(id) { }
Money getPrice() {
return Money.fromCents(
data.findProductById(id).price,
environment.currentCurrency
)
}
Money getPriceWithRebate() {
return getPrice().applyRebate(rebate);
}
private:
const ProductId id;
}
Kemudian, caching dapat ditambahkan (dalam C #, orang akan menggunakan Lazy<T>
, membuat kode pendek dan mudah; Saya tidak tahu apakah ada yang setara dalam C ++):
class Product {
public:
Product(ProductId id) : id(id) { }
Money getPrice() {
if (priceCache == NULL) {
priceCache = Money.fromCents(
data.findProductById(id).price,
environment.currentCurrency
)
return priceCache;
}
Money getPriceWithRebate() {
return getPrice().applyRebate(rebate);
}
private:
const ProductId id;
Money priceCache;
}
Kedua perubahan difokuskan pada pengambil dan bidang dukungan, kode yang tersisa tidak terpengaruh. Jika, sebagai gantinya, saya telah menggunakan bidang alih-alih pengambil getPriceWithRebate
, saya harus mencerminkan perubahan di sana juga.
Contoh di mana seseorang mungkin akan menggunakan bidang pribadi:
class Product {
public:
Product(ProductId id) : id(id) { }
ProductId getId() const { return id; }
Money getPrice() {
return Money.fromCents(
data.findProductById(id).price, // ← Accessing `id` directly.
environment.currentCurrency
)
}
private:
const ProductId id;
}
Pencari mudah: itu adalah representasi langsung dari bidang konstan (mirip dengan C # 's readonly
) yang tidak diharapkan untuk berubah di masa depan: kemungkinan, ID pengambil tidak akan pernah menjadi nilai yang dihitung. Jadi sederhanakan, dan akses bidang secara langsung.
Manfaat lain adalah bahwa getId
mungkin dihapus di masa depan jika tampaknya tidak digunakan di luar (seperti pada potongan kode sebelumnya).
const
: Saya berasumsi itu berarti kompiler akan menyambungkangetId
panggilan tetap dan memungkinkan Anda untuk membuat perubahan di kedua arah. (Kalau tidak, saya sepenuhnya setuju dengan alasan Anda untuk menggunakan getter.) Dan dalam bahasa yang menyediakan sintaksis properti, ada lebih sedikit alasan untuk tidak menggunakan properti daripada bidang dukungan secara langsung.