Anda harus menggunakan antarmuka (bukan warisan) atau semacam mekanik properti (bahkan mungkin sesuatu yang berfungsi seperti kerangka deskripsi sumber daya).
Begitu juga
interface Colored {
Color getColor();
}
class ColoredBook extends Book implements Colored {
...
}
atau
class PropertiesHolder {
<T> extends Property<?>> Optional<T> getProperty( Class<T> propertyClass ) { ... }
<V, T extends Property<V>> Optional<V> getPropertyValue( Class<T> propertyClass ) { ... }
}
interface Property<T> {
String getName();
T getValue();
}
class ColorProperty implements Property<Color> {
public Color getValue() { ... }
public String getName() { return "color"; }
}
class Book extends PropertiesHolder {
}
Klarifikasi (edit):
Cukup menambahkan bidang opsional di kelas entitas
Terutama dengan Opsional-wrapper (edit: lihat jawaban 4castle ) Saya pikir ini (menambahkan bidang dalam entitas asli) adalah cara yang layak untuk menambahkan properti baru dalam skala kecil. Masalah terbesar dengan pendekatan ini adalah bahwa itu mungkin bekerja melawan kopling rendah.
Bayangkan kelas buku Anda didefinisikan dalam proyek khusus untuk model domain Anda. Sekarang Anda menambahkan proyek lain yang menggunakan model domain untuk melakukan tugas khusus. Tugas ini membutuhkan properti tambahan di kelas buku. Entah Anda berakhir dengan warisan (lihat di bawah) atau Anda harus mengubah model domain umum untuk memungkinkan tugas baru. Dalam kasus terakhir Anda mungkin berakhir dengan banyak proyek yang semuanya tergantung pada sifat mereka sendiri ditambahkan ke kelas buku sedangkan kelas buku itu sendiri dengan cara tergantung pada proyek-proyek ini, karena Anda tidak dapat memahami kelas buku tanpa proyek tambahan.
Mengapa warisan bermasalah ketika datang ke cara untuk memberikan properti tambahan?
Ketika saya melihat contoh kelas Anda "Buku", saya berpikir tentang objek domain yang seringkali memiliki banyak bidang dan subtipe opsional. Bayangkan saja Anda ingin menambahkan properti untuk buku yang menyertakan CD. Sekarang ada empat jenis buku: buku, buku dengan warna, buku dengan CD, buku dengan warna dan CD. Anda tidak dapat menggambarkan situasi ini dengan warisan di Jawa.
Dengan antarmuka, Anda menghindari masalah ini. Anda dapat dengan mudah menyusun properti dari kelas buku tertentu dengan antarmuka. Delegasi dan komposisi akan membuatnya mudah untuk mendapatkan kelas yang Anda inginkan. Dengan warisan Anda biasanya berakhir dengan beberapa properti opsional di kelas yang hanya ada karena kelas saudara membutuhkannya.
Bacaan lebih lanjut mengapa pewarisan seringkali merupakan ide bermasalah:
Mengapa warisan umumnya dipandang sebagai hal yang buruk oleh para pendukung OOP
JavaWorld: Mengapa meluas itu jahat
Masalah dengan mengimplementasikan seperangkat antarmuka untuk menyusun seperangkat properti
Ketika Anda menggunakan antarmuka untuk ekstensi semuanya baik-baik saja selama Anda hanya memiliki satu set kecil dari mereka. Terutama ketika model objek Anda digunakan dan diperluas oleh pengembang lain, misalnya di perusahaan Anda, jumlah antarmuka akan bertambah. Dan akhirnya Anda akhirnya membuat "antarmuka properti" resmi baru yang menambahkan metode yang sudah digunakan rekan kerja Anda dalam proyek mereka untuk pelanggan X untuk kasus penggunaan yang sama sekali tidak terkait - Ugh.
sunting: Aspek penting lainnya disebutkan oleh gnasher729 . Anda sering ingin secara dinamis menambahkan properti opsional ke objek yang ada. Dengan pewarisan atau antarmuka Anda harus membuat ulang seluruh objek dengan kelas lain yang jauh dari opsional.
Ketika Anda mengharapkan ekstensi ke model objek Anda sedemikian rupa, Anda akan lebih baik dengan secara eksplisit memodelkan kemungkinan ekstensi dinamis . Saya mengusulkan sesuatu seperti di atas di mana setiap "ekstensi" (dalam hal ini properti) memiliki kelasnya sendiri. Kelas berfungsi sebagai namespace dan pengidentifikasi untuk ekstensi. Ketika Anda mengatur konvensi penamaan paket sesuai dengan cara ini memungkinkan jumlah tak terbatas ekstensi tanpa mencemari namespace untuk metode di kelas entitas asli.
Dalam pengembangan game, Anda sering menghadapi situasi di mana Anda ingin membuat perilaku dan data dalam banyak variasi. Inilah sebabnya mengapa arsitektur pola entitas-komponen-sistem menjadi cukup populer di kalangan pengembangan game. Ini juga merupakan pendekatan menarik yang mungkin ingin Anda lihat, ketika Anda mengharapkan banyak ekstensi untuk model objek Anda.