Haruskah saya menghindari menggunakan warisan objek sebanyak mungkin untuk mengembangkan game?

36

Saya lebih suka fitur OOP ketika mengembangkan game dengan Unity. Saya biasanya membuat kelas dasar (sebagian besar abstrak) dan menggunakan objek warisan untuk berbagi fungsi yang sama ke berbagai objek lainnya.

Namun, saya baru-baru ini mendengar dari seseorang bahwa menggunakan warisan harus dihindari, dan kita harus menggunakan antarmuka saja. Jadi saya bertanya mengapa, dan dia berkata bahwa "Benda warisan tentu saja penting, tetapi jika ada banyak objek yang diperluas, hubungan antar kelas sangat dalam.

Saya menggunakan kelas dasar abstrak, sesuatu seperti WeaponBasedan menciptakan kelas senjata tertentu seperti Shotgun, AssaultRifle, Machinegunsesuatu seperti itu. Ada begitu banyak keuntungan, dan satu pola yang sangat saya nikmati adalah polimorfisme. Saya dapat memperlakukan objek yang dibuat oleh subclass seolah-olah mereka adalah kelas dasar, sehingga logikanya dapat dikurangi secara drastis dan dibuat lebih dapat digunakan kembali. Jika saya perlu mengakses bidang atau metode dari sub-kelas, saya melemparkan kembali ke sub-kelas.

Saya tidak ingin mendefinisikan bidang yang sama, yang biasa digunakan dalam kelas yang berbeda, seperti AudioSource/ Rigidbody/ Animatordan banyak bidang anggota I didefinisikan seperti fireRate, damage, range, spreaddan sebagainya. Juga dalam beberapa kasus, beberapa metode dapat ditimpa. Jadi saya menggunakan metode virtual dalam kasus itu, sehingga pada dasarnya saya bisa memanggil metode itu menggunakan metode dari kelas induk, tetapi jika logikanya harus berbeda pada anak, saya telah secara manual menimpa mereka.

Jadi, haruskah semua hal ini ditinggalkan sebagai praktik buruk? Haruskah saya menggunakan antarmuka saja?

modernator
sumber
30
"Ada begitu banyak keuntungan, dan satu pola yang sangat saya nikmati adalah polimorfisme." Polimorfisme bukanlah suatu pola. Ini benar-benar inti dari OOP. Hal-hal lain seperti bidang umum dll dapat dengan mudah dicapai tanpa duplikasi atau pewarisan kode.
Cubic
3
Apakah orang yang menyarankan Anda antarmuka lebih baik daripada warisan memberi Anda argumen? Saya penasaran.
Hawker65
1
@Cubic Saya tidak pernah mengatakan bahwa polimorfisme adalah sebuah pola. Saya berkata "... satu pola yang sangat saya nikmati adalah polimorfisme". Ini berarti bahwa pola yang benar-benar saya nikmati adalah menggunakan "polimorfisme", bukan polimorfisme yang merupakan pola.
modernator
4
Orang-orang menggembar-gemborkan penggunaan antarmuka atas warisan dalam segala bentuk pengembangan. Namun, itu cenderung menambah banyak overhead, disonansi kognitif, mengarah ke ledakan kelas, sering menambah nilai yang dipertanyakan dan biasanya tidak bersinergi dengan baik dalam suatu sistem kecuali SEMUA ORANG dalam proyek mengikuti fokus pada antarmuka. Jadi jangan tinggalkan warisan dulu. Namun, game memiliki beberapa karakteristik unik dan arsitektur Unity mengharapkan Anda untuk menggunakan paradigma desain CES, itulah sebabnya Anda harus mengubah pendekatan Anda. Bacalah seri Eric Lippert's Wizards and Warriors yang menguraikan masalah jenis permainan.
Dunk
2
Saya akan mengatakan bahwa antarmuka adalah kasus pewarisan khusus di mana kelas dasar tidak berisi bidang data. Saya pikir sarannya adalah untuk mencoba tidak membangun pohon besar di mana setiap objek harus diklasifikasikan, tetapi banyak pohon kecil berdasarkan antarmuka di mana Anda dapat mengambil keuntungan dari banyak pewarisan. Polimorfisme tidak hilang dengan antarmuka.
Emanuele Paolini

Jawaban:

65

Mendukung komposisi daripada warisan dalam entitas Anda dan sistem inventaris / item. Saran ini cenderung berlaku untuk struktur logika game, ketika cara Anda dapat merakit hal-hal yang kompleks (saat runtime) dapat menyebabkan banyak kombinasi yang berbeda; saat itulah kami lebih suka komposisi.

Pilih warisan daripada komposisi dalam logika tingkat aplikasi Anda, mulai dari konstruksi UI hingga layanan. Sebagai contoh,

Widget->Button->SpinnerButton atau

ConnectionManager->TCPConnectionManagervs ->UDPConnectionManager.

... ada hirarki derivasi yang didefinisikan dengan jelas di sini, daripada banyak derivasi potensial, jadi lebih mudah untuk menggunakan warisan.

Intinya : gunakan warisan di mana Anda bisa, tetapi gunakan komposisi di mana Anda harus. PS Alasan lain kita dapat mendukung komposisi dalam sistem entitas adalah bahwa biasanya ada banyak entitas, dan warisan dapat menimbulkan biaya kinerja untuk mengakses anggota pada setiap objek; lihat tabel .

Insinyur
sumber
10
Warisan tidak menyiratkan bahwa semua metode akan menjadi virtual. Jadi itu tidak secara otomatis menyebabkan biaya kinerja. VTable hanya berperan dalam mengirimkan panggilan virtual , bukan dalam mengakses anggota data.
Ruslan
1
@Ruslan Saya telah menambahkan kata 'mungkin' dan 'dapat' untuk mengakomodasi komentar Anda. Kalau tidak, demi menjaga agar jawaban tetap ringkas, saya tidak terlalu banyak merinci. Terima kasih.
Insinyur
7
P.S. The other reason we may favour composition in entity systems is ... performance: Apakah ini benar? Melihat halaman WIkipedia yang ditautkan oleh @Linaith menunjukkan, bahwa Anda harus membuat objek antarmuka Anda. Karenanya, Anda memiliki (masih atau bahkan lebih) panggilan fungsi virtual dan lebih banyak cache misses, saat Anda memperkenalkan tingkat tipuan lainnya.
Flamefire
1
@ Api Api Ya, itu benar; ada beberapa cara untuk mengatur data Anda sedemikian rupa sehingga efisiensi cache Anda optimal, apa pun, dan tentu saja jauh lebih optimal daripada tipuan ekstra itu. Ini tidak warisan dan yang komposisi, meskipun lebih dalam array-of-struct / struct-of-array akal (disisipkan / data non-interleaved dalam pengaturan cache-linear), membelah menjadi array terpisah dan kadang-kadang duplikasi data ke mencocokkan set operasi di berbagai bagian pipa Anda. Tetapi sekali lagi, untuk masuk ke sini akan ada pengalihan yang sangat besar yang sebaiknya dihindari demi keputusan.
Insinyur
2
Harap ingat untuk menyimpan komentar pada permintaan sipil untuk klarifikasi atau kritik dan memperdebatkan isi ide dan bukan karakter atau pengalaman orang yang menyatakannya.
Josh
18

Anda sudah mendapatkan beberapa jawaban yang bagus, tetapi gajah besar di ruangan dalam pertanyaan Anda adalah yang ini:

mendengar dari seseorang bahwa menggunakan warisan harus dihindari, dan kita harus menggunakan antarmuka saja

Sebagai aturan praktis, ketika seseorang memberi Anda aturan praktis, maka abaikan saja. Ini tidak hanya berlaku untuk "seseorang memberi tahu Anda sesuatu", tetapi juga untuk membaca hal-hal di internet. Kecuali Anda tahu mengapa (dan dapat benar-benar berdiri di belakangnya), nasihat semacam itu tidak berharga dan seringkali sangat berbahaya.

Dalam pengalaman saya, konsep yang paling penting, dan membantu dalam OOP adalah "kopling rendah" dan "kohesi tinggi" (kelas / objek tahu sesedikit mungkin tentang satu sama lain, dan setiap unit bertanggung jawab atas sesedikit mungkin hal).

Kopling rendah

Ini berarti bahwa setiap "bundel barang" dalam kode Anda harus bergantung pada lingkungannya sesedikit mungkin. Ini berlaku untuk kelas (desain kelas) tetapi juga objek (implementasi aktual), "file" secara umum (yaitu, jumlah #includes per satu.cpp file , jumlah importper .javafile tunggal dan sebagainya).

Tanda bahwa dua entitas digabungkan adalah bahwa salah satu dari mereka akan rusak (atau perlu diubah) ketika yang lain diubah dengan cara apa pun.

Warisan meningkatkan sambungan, jelas; mengubah kelas dasar mengubah semua subclass.

Antarmuka mengurangi kopling: dengan mendefinisikan kontrak berbasis metode yang jelas, Anda dapat mengubah apa pun tentang kedua sisi antarmuka secara bebas, selama Anda tidak mengubah kontrak. (Perhatikan bahwa "antarmuka" adalah konsep umum, interfacekelas abstrak Java atau C ++ hanyalah detail implementasi).

Kohesi Tinggi

Ini berarti setiap kelas, objek, file dll. Menjadi perhatian atau bertanggung jawab untuk sesedikit mungkin. Yaitu, hindari kelas besar yang melakukan banyak hal. Dalam contoh Anda, jika senjata Anda memiliki aspek yang benar-benar terpisah (amunisi, perilaku menembak, representasi grafis, representasi inventaris, dll.), Maka Anda dapat memiliki kelas berbeda yang mewakili tepat satu dari hal-hal itu. Kelas senjata utama kemudian berubah menjadi "pemegang" perincian itu; objek senjata kemudian sedikit lebih dari beberapa petunjuk untuk detail itu.

Dalam contoh ini, Anda akan memastikan bahwa kelas Anda yang mewakili "Perilaku Menembak" tahu sesedikit mungkin secara manusiawi tentang kelas senjata utama. Secara optimal, tidak ada sama sekali. Misalnya, ini berarti bahwa Anda dapat memberikan "Perilaku Menembak" ke objek apa pun di dunia Anda (menara, gunung berapi, NPC ...) hanya dengan satu jentikan jari. Jika suatu saat Anda ingin mengubah cara senjata direpresentasikan dalam inventaris, maka Anda dapat melakukannya - hanya kelas inventaris Anda yang mengetahui hal itu sama sekali.

Tanda bahwa suatu entitas tidak kohesif adalah jika ia tumbuh lebih besar dan lebih besar, bercabang ke beberapa arah secara bersamaan.

Warisan seperti yang Anda gambarkan mengurangi kohesi - kelas senjata Anda, pada akhirnya, adalah bongkahan besar yang menangani segala macam aspek yang berbeda, yang tidak terkait dengan senjata Anda.

Antarmuka secara tidak langsung meningkatkan kohesi dengan secara jelas memisahkan tanggung jawab antara kedua sisi antarmuka.

Apa yang harus dilakukan sekarang

Masih belum ada aturan yang keras dan cepat, semua ini hanyalah pedoman. Secara umum, sebagai pengguna TKK yang disebutkan dalam jawabannya, warisan diajarkan banyak di sekolah dan buku; itu adalah hal-hal mewah tentang OOP. Antarmuka mungkin lebih membosankan untuk diajarkan, dan juga (jika Anda melewati contoh-contoh sepele) sedikit lebih sulit, membuka bidang injeksi ketergantungan, yang tidak begitu jelas sebagai warisan.

Pada akhirnya, skema berbasis warisan Anda masih lebih baik daripada tidak memiliki desain OOP yang jelas. Jadi jangan ragu untuk tetap menggunakannya. Jika Anda mau, Anda dapat merenungkan / google sedikit tentang Kopling Rendah, Kohesi Tinggi dan lihat apakah Anda ingin menambahkan pemikiran semacam itu ke gudang senjata Anda. Anda selalu dapat menolak untuk mencobanya jika ingin, nanti; atau coba pendekatan berbasis antarmuka pada modul kode baru berikutnya yang lebih besar.

AnoE
sumber
Terima kasih atas penjelasan terperinci. Sangat membantu untuk memahami apa yang saya lewatkan.
modernator
13

Gagasan bahwa pewarisan harus dihindari sama sekali salah.

Ada prinsip pengkodean yang disebut Composition over Inheritance . Dikatakan bahwa Anda dapat mencapai hal yang sama dengan komposisi, dan itu lebih disukai, karena Anda dapat menggunakan kembali beberapa kode. Lihat Mengapa saya lebih suka komposisi daripada warisan?

Saya harus mengatakan saya suka kelas senjatamu dan akankah ia melakukan hal yang sama. Tapi saya belum membuat game sekarang ...

Seperti yang ditunjukkan oleh James Trotter, komposisi dapat memiliki beberapa keuntungan, terutama dalam fleksibilitas saat runtime untuk mengubah cara kerja senjata. Ini mungkin dengan warisan, tetapi lebih sulit.

Linaith
sumber
14
Alih-alih memiliki kelas untuk senjata, Anda bisa memiliki satu kelas "senjata", dan komponen untuk menangani apa yang dilakukan oleh tembakan, lampiran apa yang dimilikinya dan apa yang mereka lakukan, apa yang dimiliki "penyimpanan amunisi" yang dimilikinya, Anda dapat membangun banyak konfigurasi , beberapa di antaranya dapat berupa "senapan" atau "senapan serbu", tetapi itu juga dapat diubah pada saat run time misalnya untuk mematikan lampiran dan mengubah kapasitas majalah, dll. Atau seluruh konfigurasi senjata baru dapat dibuat yang bahkan tidak memikirkan awalnya. Ya, Anda dapat mencapai sesuatu yang mirip dengan warisan, tetapi tidak semudah itu.
Trotski94
3
@ JamesTrotter Pada titik ini, saya memikirkan Borderlands dan senjatanya, dan bertanya-tanya betapa mengerikannya ini hanya dengan warisan ...
Baldrickk
1
@ JamesTrotter Saya berharap itu adalah jawaban dan bukan komentar.
Pharap
6

Masalahnya adalah bahwa warisan mengarah ke penggandengan - objek Anda perlu tahu lebih banyak tentang satu sama lain. Itu sebabnya aturannya adalah "Selalu mendukung komposisi daripada warisan". Ini tidak berarti TIDAK PERNAH menggunakan warisan, itu berarti menggunakannya di tempat yang benar-benar sesuai, tetapi jika Anda pernah duduk di sana berpikir "Saya bisa melakukan ini dengan dua cara dan keduanya masuk akal", langsung saja ke komposisi.

Warisan juga bisa menjadi semacam pembatas. Anda memiliki "WeaponBase" yang bisa menjadi AssultRifle - dahsyat. Apa yang terjadi ketika Anda memiliki senapan laras ganda dan ingin membiarkan laras menyala secara mandiri - sedikit lebih keras tetapi bisa dilakukan, Anda hanya memiliki kelas laras tunggal dan laras ganda, tetapi Anda tidak bisa hanya memasang 2 barel tunggal dengan senjata yang sama, bukan? Bisakah Anda mod satu untuk memiliki 3 barel atau apakah Anda memerlukan kelas baru untuk itu?

Bagaimana dengan AssultRifle dengan GrenadeLauncher di bawahnya - hmm, sedikit lebih keras. Bisakah Anda mengganti GrenadeLauncher dengan senter untuk berburu malam hari?

Terakhir, bagaimana Anda mengizinkan pengguna membuat senjata sebelumnya dengan mengedit file konfigurasi? Ini sulit karena Anda memiliki hubungan kode-keras yang mungkin lebih baik disusun dan dikonfigurasi dengan data.

Warisan berganda dapat memperbaiki beberapa contoh sepele ini, tetapi menambah beberapa masalah.

Sebelum ada perkataan umum seperti "Lebih suka komposisi daripada warisan", saya menemukan ini dengan menulis pohon warisan yang terlalu rumit (yang menyenangkan dan bekerja dengan sempurna) kemudian menemukan bahwa itu benar-benar sulit untuk dimodifikasi dan dipelihara kemudian. Perkataan ini hanya supaya Anda memiliki cara alternatif dan ringkas untuk belajar dan mengingat konsep seperti itu tanpa harus melalui seluruh pengalaman - tetapi jika Anda ingin menggunakan warisan secara besar-besaran, saya sarankan untuk tetap berpikiran terbuka dan mengevaluasi seberapa baik kerjanya untuk Anda - tidak ada hal buruk yang akan terjadi jika Anda menggunakan banyak warisan dan itu mungkin merupakan pengalaman belajar yang hebat paling buruk (paling-paling itu mungkin bekerja dengan baik untuk Anda)

Bill K
sumber
2
"Bagaimana Anda mengizinkan pengguna membuat senjata sebelumnya dengan mengedit file konfigurasi?" -> Pola yang biasanya saya lakukan adalah membuat kelas akhir untuk setiap senjata. Misalnya, seperti Glock17. Pertama buat kelas WeaponBase. Kelas ini diabstraksikan, mendefinisikan nilai-nilai umum seperti mode api, laju kebakaran, ukuran majalah, maks amunisi, pelet. Juga menangani input pengguna, seperti mouse1 / mouse2 / reload dan memanggil metode yang sesuai. Mereka hampir virtual, atau dipecah menjadi lebih banyak fungsi sehingga pengembang dapat mengesampingkan fungsi dasar jika diperlukan. Dan kemudian membuat kelas lain yang memperluas WeaponBase,
modernator
2
sesuatu seperti SlideStoppableWeapon. Sebagian besar pistol punya ini, dan ini menangani perilaku tambahan seperti slide berhenti. Akhirnya buat kelas Glock17 yang memanjang dari SlideStoppableWeapon. Glock17 adalah kelas terakhir, jika pistol memiliki kemampuan unik yang hanya dimiliki, akhirnya ditulis di sini. Saya biasanya menggunakan pola ini ketika pistol memiliki mekanisme penembakan khusus atau mekanisme muat ulang. Menerapkan perilaku unik itu hingga akhir hirarki kelas, menggabungkan logika umum sebanyak mungkin dari orang tua.
modernator
2
@modernator Seperti yang saya katakan, itu hanya panduan - jika Anda tidak mempercayainya, silakan abaikan saja, tetap buka mata Anda mengenai hasil dari waktu ke waktu dan evaluasi manfaat vs rasa sakit sesering mungkin. Saya mencoba mengingat tempat-tempat yang saya matikan jari kaki saya dan membantu orang lain menghindari hal yang sama, tetapi apa yang berhasil bagi saya mungkin tidak berhasil untuk Anda.
Bill K
7
@modernator Di Minecraft mereka membuat Monstersubkelas dari WalkingEntity. Kemudian mereka menambahkan slime. Menurut Anda seberapa baik itu berhasil?
user253751
1
@immibis Apakah Anda memiliki referensi atau tautan anekdotal untuk masalah itu? Googling kata kunci minecraft menenggelamkan saya di tautan video ;-)
Peter - Reinstate Monica
3

Bertentangan dengan jawaban yang lain, ini tidak ada hubungannya dengan pewarisan vs komposisi. Warisan vs komposisi adalah keputusan yang Anda buat tentang bagaimana kelas akan diimplementasikan. Antarmuka vs kelas adalah keputusan yang datang sebelumnya.

Antarmuka adalah warga negara kelas satu dari bahasa OOP. Kelas adalah detail implementasi sekunder. Pikiran programmer baru sangat dilanggar oleh guru dan buku yang memperkenalkan kelas dan warisan sebelum antarmuka.

Prinsip kuncinya adalah bahwa bila memungkinkan, jenis semua parameter metode dan nilai pengembalian harus berupa antarmuka, bukan kelas. Ini membuat API Anda jauh lebih fleksibel dan kuat. Sebagian besar waktu, metode Anda dan penelepon mereka seharusnya tidak memiliki alasan untuk mengetahui atau peduli tentang kelas sebenarnya dari objek yang mereka hadapi. Jika API Anda agnostik tentang detail implementasi, Anda dapat dengan bebas beralih antara komposisi dan pewarisan tanpa merusak apa pun.

Tidak u
sumber
Jika antarmuka adalah warga kelas pertama dari bahasa OOP apa pun, saya ingin tahu apakah Python, Ruby, ... bukan bahasa OOP.
BlackJack
@ BlackJack: Di Ruby, antarmuka tersirat (mengetik bebek jika Anda mau), dan diekspresikan dengan menggunakan komposisi alih-alih warisan (juga, ia memiliki Mixin yang berada di suatu tempat di antaranya, sejauh yang saya ketahui) ...
AnoE
@BlackJack "Antarmuka" (konsep) tidak memerlukan interface(kata kunci bahasa).
Caleth
2
@Caleth Tapi menyebut mereka warga negara kelas pertama tidak IMHO. Ketika deskripsi bahasa mengklaim sesuatu adalah warga negara kelas satu , biasanya itu berarti sesuatu yang nyata dalam bahasa itu yang memiliki jenis dan nilai dan dapat diedarkan. Kelas suka adalah warga negara kelas satu di Python, begitu pula fungsi, metode, dan modul. Jika kita berbicara tentang konsep, maka antarmuka juga merupakan bagian dari semua bahasa non-OOP.
BlackJack
2

Setiap kali seseorang memberi tahu Anda bahwa satu pendekatan spesifik adalah yang terbaik untuk semua kasus, itu sama dengan memberi tahu Anda bahwa satu dan obat yang sama menyembuhkan semua penyakit.

Warisan vs komposisi adalah pertanyaan is-a vs has-a. Antarmuka adalah cara lain (ke-3), cocok untuk beberapa situasi.

Inheritance, atau is-a logic: Anda menggunakannya ketika kelas baru akan berperilaku dan digunakan sepenuhnya seperti (secara lahiriah) kelas lama tempat Anda berasal, jika kelas baru akan diekspos ke publik semua fungsi yang dimiliki kelas lama ... lalu Anda warisi.

Komposisi, atau memiliki-logika: Jika kelas baru hanya perlu menggunakan kelas lama secara internal, tanpa memaparkan fitur kelas lama ke publik, maka Anda menggunakan komposisi - yaitu, memiliki instance dari kelas lama sebagai properti anggota atau variabel yang baru. (Ini bisa menjadi properti pribadi, atau dilindungi, atau apa pun, tergantung pada kasus penggunaan). Poin kunci di sini adalah bahwa ini adalah kasus penggunaan di mana Anda tidak ingin mengekspos fitur kelas asli dan digunakan kepada publik, cukup gunakan secara internal, sedangkan dalam kasus warisan Anda memaparkannya kepada publik, melalui kelas baru. Terkadang Anda membutuhkan satu pendekatan, dan terkadang yang lain.

Antarmuka: Antarmuka adalah untuk kasus penggunaan lain - ketika Anda ingin kelas baru untuk sebagian dan tidak sepenuhnya menerapkan dan mengekspos ke publik fungsi dari yang lama. Ini memungkinkan Anda memiliki kelas baru, kelas dari hierarki yang sama sekali berbeda dari yang lama, berperilaku seperti yang lama dalam beberapa aspek saja.

Katakanlah Anda memiliki berbagai macam makhluk yang diwakili oleh kelas, dan mereka memiliki fungsi yang diwakili oleh berbagai fungsi. Misalnya, burung akan memiliki Talk (), Fly () dan Poop (). Class Duck akan mewarisi dari Bird kelas, menerapkan semua fitur.

Class Fox, jelas, tidak bisa terbang. Jadi jika Anda mendefinisikan leluhur untuk memiliki semua fitur, maka Anda tidak dapat menurunkan keturunan dengan benar.

Namun, jika Anda memecah fitur menjadi grup, mewakili setiap kelompok panggilan dengan antarmuka, katakan, JIKA, berisi Takeoff (), FlapWings () dan Land (), maka Anda bisa untuk fungsi implementasi kelas Fox dari ITalk dan IPoop tapi tidak JIKA. Anda kemudian akan mendefinisikan variabel dan parameter untuk menerima objek yang mengimplementasikan antarmuka spesifik, dan kemudian kode yang bekerja dengan mereka akan tahu apa yang bisa dipanggil ... dan selalu dapat meminta untuk antarmuka lain, jika perlu melihat apakah fungsi lain juga diimplementasikan untuk objek saat ini.

Masing-masing pendekatan ini memiliki kasus penggunaan ketika itu yang terbaik, tidak ada pendekatan yang merupakan solusi terbaik mutlak untuk semua kasus.

Dragan Juric
sumber
1

Untuk gim, terutama dengan Unity, yang berfungsi dengan arsitektur entitas-komponen, Anda harus memilih komposisi daripada pewarisan untuk komponen gim Anda. Ini jauh lebih fleksibel, dan menghindari masuk ke situasi di mana Anda ingin entitas game "menjadi" dua hal yang berada di daun berbeda dari pohon warisan.

Jadi, misalnya, katakan Anda memiliki TalkingAI di satu cabang pohon warisan, dan VolumetricCloud di cabang lain yang terpisah, dan Anda ingin cloud yang berbicara. Ini sulit dengan pohon warisan yang dalam. Dengan entitas-komponen, Anda hanya membuat entitas yang memiliki komponen TalkingAI dan Cloud, dan Anda siap melakukannya.

Tetapi itu tidak berarti bahwa dalam, katakanlah, implementasi cloud volumetrik Anda, Anda seharusnya tidak menggunakan warisan. Kode untuk itu mungkin substansial dan terdiri dari beberapa kelas, dan Anda dapat menggunakan OOP sesuai kebutuhan. Tapi itu semua akan berjumlah satu komponen game.

Sebagai catatan, saya mengambil beberapa masalah dengan ini:

Saya biasanya membuat kelas dasar (sebagian besar abstrak) dan menggunakan objek warisan untuk berbagi fungsi yang sama ke berbagai objek lainnya.

Warisan bukan untuk penggunaan kembali kode. Ini untuk membangun hubungan is-a . Banyak waktu ini berjalan seiring, tetapi Anda harus berhati-hati. Hanya karena dua modul mungkin perlu menggunakan kode yang sama, itu tidak berarti bahwa satu dari jenis yang sama dengan yang lain.

Anda dapat menggunakan antarmuka jika Anda ingin, katakanlah, memiliki List<IWeapon>dengan berbagai jenis senjata di dalamnya. Dengan cara ini, Anda dapat mewarisi dari antarmuka IWeapon, dan subkelas MonoBehaviour untuk semua senjata, dan menghindari masalah apa pun dengan tidak adanya pewarisan berganda.

Sava B.
sumber
-3

Anda sepertinya tidak mengerti apa itu antarmuka atau tidak. Butuh waktu sekitar 10+ tahun untuk berpikir tentang OO dan mengajukan beberapa pertanyaan kepada orang-orang yang benar-benar pintar adalah apakah saya dapat memiliki momen ah-ha dengan antarmuka. Semoga ini membantu.

Yang terbaik adalah menggunakan kombinasi keduanya. Dalam OO mind modelling dunia dan orang-orang katakanlah, beberapa contoh yang mendalam. Jiwa dihubungkan dengan tubuh melalui pikiran. Pikiran ADALAH penghubung antara jiwa (beberapa menganggap intelek) dan perintah yang dikeluarkannya kepada tubuh. Antarmuka pikiran dengan tubuh adalah sama untuk semua orang, secara fungsional.

Analogi yang sama dapat digunakan antara orang (tubuh dan jiwa) yang berinteraksi dengan dunia. Tubuh adalah penghubung antara pikiran dan dunia. Semua orang berinteraksi dengan dunia dengan cara yang sama, satu-satunya keunikan adalah BAGAIMANA kami berinteraksi dengan dunia, yaitu bagaimana kami menggunakan PIKIRAN kami untuk MEMUTUSKAN BAGAIMANA kami berinteraksi / berinteraksi di dunia.

Sebuah antarmuka kemudian hanyalah sebuah mekanisme untuk menghubungkan struktur OO Anda dengan struktur OO lain yang berbeda dengan masing-masing pihak memiliki atribut yang berbeda yang harus bernegosiasi / memetakan satu sama lain untuk menghasilkan beberapa keluaran fungsional dalam media / lingkungan yang berbeda.

Jadi bagi pikiran untuk memanggil fungsi open-hand, ia harus mengimplementasikan interface nervous_command_system dengan BAHWA memiliki API sendiri dengan instruksi bagaimana mengimplementasikan semua persyaratan yang diperlukan sebelum memanggil open-hand.

Christopher Hoffman
sumber