Saya harap ocehan ini akan memperjelas pertanyaan saya - saya benar-benar mengerti jika mereka tidak mau, jadi beri tahu saya jika itu masalahnya, dan saya akan mencoba membuat diri saya lebih jelas.
Meet BoxPong , game yang sangat sederhana yang saya buat untuk berkenalan dengan pengembangan game berorientasi objek. Seret kotak untuk mengontrol bola dan mengumpulkan benda-benda kuning.
Membuat BoxPong membantu saya merumuskan, antara lain, pertanyaan mendasar: bagaimana saya bisa memiliki objek yang berinteraksi satu sama lain tanpa harus "saling memiliki"? Dengan kata lain, adakah cara agar objek tidak hierarkis, melainkan hidup berdampingan? (Saya akan pergi ke detail lebih lanjut di bawah ini.)
Saya menduga masalah objek yang hidup berdampingan adalah masalah umum, jadi saya berharap ada cara yang mapan untuk menyelesaikannya. Saya tidak ingin menemukan kembali roda persegi, jadi saya kira jawaban ideal yang saya cari adalah "inilah pola desain yang biasa digunakan untuk menyelesaikan masalah Anda."
Terutama di gim-gim sederhana seperti BoxPong, jelas ada, atau seharusnya ada, beberapa benda yang hidup berdampingan di tingkat yang sama. Ada sebuah kotak, ada sebuah bola, ada sebuah koleksi. Yang bisa saya ungkapkan dalam bahasa berorientasi objek, meskipun - atau begitulah tampaknya - adalah hubungan HAS-A yang ketat . Itu dilakukan melalui variabel anggota. Saya tidak bisa begitu saja memulai ball
dan membiarkannya melakukan hal itu, saya membutuhkannya secara permanen menjadi milik objek lain. Saya telah mengaturnya sehingga objek permainan utama memiliki kotak, dan kotak itu pada gilirannya memiliki bola, dan memiliki penghitung skor. Setiap objek juga memilikiupdate()
metode, yang menghitung posisi, arah dll, dan saya pergi ke cara yang sama di sana: Saya memanggil metode pembaruan objek permainan utama, yang memanggil metode pembaruan semua anak-anaknya, dan mereka pada gilirannya memanggil metode pembaruan semua anak - anak mereka . Ini adalah satu-satunya cara saya bisa melihat untuk membuat game berorientasi objek, tetapi saya merasa itu bukan cara yang ideal. Lagipula, saya tidak akan menganggap bola sebagai milik kotak, melainkan berada di level yang sama dan berinteraksi dengannya. Saya kira itu bisa dicapai dengan mengubah semua objek game menjadi variabel anggota dari objek game utama, tapi saya tidak melihat itu menyelesaikan apa pun. Maksud saya ... mengesampingkan kekacauan yang jelas, bagaimana mungkin ada cara bagi bola dan kotak untuk saling mengenal , yaitu berinteraksi?
Ada juga masalah objek yang perlu saling menyampaikan informasi. Saya memiliki sedikit pengalaman menulis kode untuk SNES, di mana Anda memiliki akses ke hampir seluruh RAM sepanjang waktu. Katakanlah Anda membuat musuh khusus untuk Super Mario World , dan Anda ingin itu menghapus semua koin Mario, lalu simpan saja nol untuk mengatasi $ 0DBF, tidak masalah. Tidak ada batasan yang mengatakan musuh tidak dapat mengakses status pemain. Saya kira saya telah dimanjakan oleh kebebasan ini, karena dengan C ++ dan sejenisnya saya sering bertanya-tanya bagaimana membuat nilai dapat diakses oleh beberapa objek lain (atau bahkan global).
Menggunakan contoh BoxPong, bagaimana jika saya ingin bola memantul dari tepi layar? width
dan height
sifat-sifat Game
kelas,ball
untuk memiliki akses ke mereka. Saya bisa meneruskan nilai-nilai seperti ini (baik melalui konstruktor atau metode di mana mereka diperlukan), tetapi itu hanya menjerit praktik buruk kepada saya.
Saya kira masalah utama saya adalah bahwa saya perlu objek untuk saling mengenal, tetapi satu-satunya cara saya bisa melihatnya adalah hierarki yang ketat, yang jelek dan tidak praktis.
Saya pernah mendengar tentang "kelas teman" di C ++ dan agak tahu bagaimana mereka bekerja, tetapi jika mereka adalah solusi akhir semua, maka kenapa saya tidak melihat friend
kata kunci dituangkan di setiap proyek C ++, dan kenapa konsep tidak ada di setiap bahasa OOP? (Hal yang sama berlaku untuk pointer fungsi, yang baru saja saya pelajari.)
Terima kasih sebelumnya atas jawaban dalam bentuk apa pun - dan sekali lagi, jika ada bagian yang tidak masuk akal bagi Anda, beri tahu saya.
Jawaban:
Secara umum, ternyata sangat buruk jika objek dari tingkat yang sama tahu tentang satu sama lain. Begitu benda saling mengenal, mereka diikat, atau digabungkan satu sama lain. Ini membuat mereka sulit untuk berubah, sulit untuk diuji, sulit untuk dipertahankan.
Ini bekerja jauh lebih baik jika ada beberapa objek "di atas" yang tahu tentang keduanya dan dapat mengatur interaksi di antara mereka. Objek yang tahu tentang dua rekan dapat mengikat mereka bersama melalui injeksi ketergantungan atau melalui peristiwa atau lewat pesan (atau mekanisme decoupling lainnya). Ya, itu mengarah ke sedikit hirarki buatan, tapi itu jauh lebih baik daripada kekacauan spageti yang Anda dapatkan ketika hal-hal hanya berinteraksi mau tak mau. Itu hanya lebih penting dalam C ++, karena Anda memerlukan sesuatu untuk memiliki masa pakai objek juga.
Jadi singkatnya, Anda bisa melakukannya hanya dengan memiliki objek berdampingan di mana saja diikat bersama oleh akses ad hoc, tapi itu ide yang buruk. Hirarki menyediakan ketertiban dan kepemilikan yang jelas. Hal utama yang perlu diingat adalah bahwa objek dalam kode tidak harus objek dalam kehidupan nyata (atau bahkan game). Jika objek dalam game tidak membuat hierarki yang baik, abstraksi yang berbeda mungkin lebih baik.
sumber
Tidak!
Saya pikir masalah utama yang Anda miliki, adalah Anda menggunakan "Pemrograman Berorientasi Objek" sedikit terlalu harfiah. Dalam OOP, suatu objek tidak mewakili "benda" tetapi "ide" yang berarti bahwa "Bola", "Game", "Fisika", "Matematika", "Tanggal", dll. Semua adalah objek yang valid. Juga tidak ada persyaratan bagi objek untuk "tahu" tentang apa pun. Misalnya,
Date.Now().getTommorrow()
Akan bertanya pada komputer hari apa hari ini, menerapkan aturan tanggal misterius untuk mengetahui tanggal besok, dan mengembalikannya ke pemanggil. TheDate
objek tidak tahu tentang apa-apa lagi, hanya perlu meminta informasi yang diperlukan dari sistem. Juga,Math.SquareRoot(number)
tidak perlu tahu apa pun selain logika cara menghitung akar kuadrat.Jadi, dalam contoh Anda yang saya kutip, "Bola" seharusnya tidak tahu apa-apa tentang "Kotak". Box dan Balls adalah ide yang sangat berbeda, dan tidak memiliki hak untuk berbicara satu sama lain. Tetapi mesin Fisika memang tahu apa itu Box and Ball (atau setidaknya, ThreeDShape), dan ia tahu di mana mereka berada, dan apa yang seharusnya terjadi pada mereka. Jadi jika bola menyusut karena dingin, Mesin Fisika akan memberi tahu bola itu bahwa ia lebih kecil sekarang.
Ini seperti membangun mobil. Sebuah chip komputer tidak tahu apa-apa tentang mesin mobil, tetapi mobil dapat menggunakan chip komputer untuk mengendalikan mesin. Gagasan sederhana untuk menggunakan hal-hal kecil dan sederhana bersama-sama untuk menciptakan hal yang sedikit lebih besar, lebih kompleks, yang dengan sendirinya dapat digunakan kembali sebagai komponen dari bagian yang lebih kompleks lainnya.
Dan dalam contoh Mario Anda, bagaimana jika Anda berada di ruang tantangan di mana menyentuh musuh tidak menguras koin Marios, tetapi hanya mengeluarkannya dari ruangan itu? Adalah di luar ruang ide Mario atau musuh bahwa Mario harus kehilangan koin ketika menyentuh musuh (pada kenyataannya, jika Mario memiliki bintang kebal, Dia malah membunuh musuh). Jadi objek apa pun (domain / ide) yang bertanggung jawab atas apa yang terjadi ketika mario menyentuh musuh adalah satu-satunya yang perlu diketahui tentang keduanya, dan harus melakukan apa pun untuk salah satu dari mereka (sejauh objek itu memungkinkan perubahan yang didorong oleh eksternal) ).
Juga, dengan pernyataan Anda tentang objek yang memanggil anak-anak
Update()
, itu sangat rawan bug seperti apa jikaUpdate
disebut beberapa kali per frame dari orang tua yang berbeda? (bahkan jika Anda menangkap ini, itu adalah waktu CPU yang terbuang yang dapat memperlambat permainan Anda) Semua orang hanya boleh menyentuh apa yang mereka butuhkan, ketika mereka perlu. Jika Anda menggunakan Pembaruan (), Anda harus menggunakan beberapa bentuk pola berlangganan untuk memastikan semua Pembaruan dipanggil satu kali per bingkai (jika ini tidak ditangani untuk Anda seperti di Unity)Mempelajari cara mendefinisikan ide domain Anda menjadi blok yang jelas, terisolasi, terdefinisi dengan baik, dan mudah digunakan akan menjadi faktor terbesar dalam seberapa baik Anda dapat memanfaatkan OOP.
sumber
Anda tampaknya kehilangan titik pemrograman berorientasi objek.
Pemrograman Berorientasi Objek adalah tentang mengelola dependensi dengan secara selektif membalik dependensi kunci tertentu dalam arsitektur Anda sehingga Anda dapat mencegah kekakuan, kerapuhan, dan tidak dapat digunakan kembali.
Apa itu ketergantungan? Ketergantungan adalah ketergantungan pada sesuatu yang lain. Ketika Anda menyimpan nol untuk mengatasi $ 0DBF, Anda mengandalkan fakta bahwa alamat itu adalah tempat koin Mario berada dan bahwa koin tersebut direpresentasikan sebagai bilangan bulat. Kode Musuh Kustom Anda bergantung pada kode yang menerapkan Mario dan koinnya. Jika Anda membuat perubahan ke tempat Mario menyimpan koinnya di memori, Anda harus secara manual memperbarui semua kode yang merujuk pada lokasi memori.
Kode berorientasi objek adalah semua tentang membuat kode Anda bergantung pada abstraksi dan bukan pada detail. Jadi, bukannya
kamu akan menulis
Sekarang, jika Anda ingin mengubah cara Mario menyimpan koinnya dari int ke panjang atau ganda atau menyimpannya di jaringan atau menyimpannya di database atau memulai proses panjang lainnya, Anda membuat perubahan di satu tempat: the Kelas Mario, dan semua kode Anda yang lain terus bekerja tanpa perubahan.
Karena itu, ketika Anda bertanya
Anda benar-benar bertanya:
yang bukan pemrograman berorientasi objek.
Saya sarankan Anda mulai dengan membaca semuanya di sini: http://objectmentor.com/omSolutions/oops_what.html dan kemudian cari semuanya di youtube oleh Robert Martin dan saksikan semuanya.
Jawaban saya berasal darinya, dan beberapa di antaranya langsung dikutip darinya.
sumber
mario.coins = 0;
, tetapimario.loseCoins();
, yang baik dan benar - tetapi poin saya adalah, bagaimana mungkin musuh memiliki akses kemario
objek itu?mario
menjadi variabel anggotaenemy
tampaknya tidak benar bagi saya.Anda dapat mengaktifkan kopling longgar dengan menerapkan pola mediator. Menerapkannya mengharuskan Anda untuk memiliki referensi ke komponen mediator yang mengetahui semua komponen penerima.
Ini menyadari "pemikiran permainan, tolong biarkan ini dan itu terjadi".
Pola umum adalah pola terbitkan-berlangganan. Sangat tepat jika mediator tidak mengandung banyak logika. Kalau tidak, gunakan mediator kerajinan tangan yang tahu ke mana harus merutekan semua panggilan dan mungkin bahkan memodifikasinya.
Ada varian sinkron dan asinkron yang biasanya dinamai bus peristiwa, bus pesan, atau antrian pesan. Carilah mereka untuk menentukan apakah mereka sesuai dalam kasus khusus Anda.
sumber