Come posso avere oggetti che interagiscono e comunicano tra loro senza forzare una gerarchia?

4

Spero che queste chiacchiere chiariscano la mia domanda - Capirei assolutamente se non lo faranno, quindi fammi sapere se è così, e proverò a rendermi più chiaro.

Incontra BoxPong , un gioco molto semplice che ho fatto per familiarizzare con lo sviluppo del gioco orientato agli oggetti. Trascina la casella per controllare la palla e raccogliere le cose gialle.
Fare BoxPong mi ha aiutato a formulare, tra le altre cose, una domanda fondamentale: come posso avere oggetti che interagiscono tra loro senza dover "appartenere" l'un l'altro? In altre parole, c'è un modo per oggetti da non essere gerarchici, ma invece coesistere? (Vado in ulteriori dettagli di seguito.)

Ho il sospetto che il problema degli oggetti coesistenti sia comune, quindi spero che ci sia un modo consolidato per risolverlo. Non voglio reinventare la ruota quadrata, quindi credo che la risposta ideale che sto cercando sia "Ecco un modello di progettazione che è comunemente usato per risolvere il tuo tipo di problema."

Soprattutto nei giochi semplici come BoxPong, è chiaro che ci sono, o dovrebbero essere, una manciata di oggetti che coesistono allo stesso livello. C'è una scatola, c'è una palla, c'è un oggetto da collezione. Tutto quello che posso esprimere in linguaggi orientati agli oggetti, anche se - o così sembra - sono stringenti relazioni HAS-A . Questo è fatto attraverso le variabili dei membri. Non posso semplicemente iniziare con ball e lasciare che faccia il suo lavoro, ne ho bisogno per appartenere in modo permanente a un altro oggetto. L'ho impostato in modo che l'oggetto di gioco principale abbia una casella, e la casella a sua volta abbia una palla, e abbia un punteggio contatore. Ogni oggetto ha anche un metodo update() , che calcola la posizione, la direzione ecc. E io vado in un modo simile lì: chiamo il metodo di aggiornamento dell'oggetto principale del gioco, che chiama i metodi di aggiornamento di tutti i suoi figli, e a loro volta chiamano i metodi di aggiornamento di tutti i loro bambini. Questo è l'unico modo che posso vedere per creare un gioco orientato agli oggetti, ma ritengo che non sia il modo ideale. Dopotutto, non penserei esattamente alla palla come alla scatola, ma piuttosto allo stesso livello e all'interazione con essa. Suppongo che ciò possa essere ottenuto trasformando tutti gli oggetti di gioco in variabili membro dell'oggetto principale del gioco, ma non vedo che risolva nulla. Voglio dire ... lasciando da parte il disordine ovvio, come ci sarebbe un modo per la palla e la scatola di conoscersi , cioè di interagire?

C'è anche il problema degli oggetti che devono passare le informazioni tra loro. Ho un bel po 'di esperienza nella scrittura del codice per SNES, in cui si ha accesso praticamente all'intera RAM tutto il tempo. Supponiamo che tu stia creando un nemico personalizzato per Super Mario World e vuoi che rimuova tutte le monete di Mario, quindi memorizza zero per l'indirizzo $ 0DBF, nessun problema. Non ci sono limitazioni che dicono che i nemici non possono accedere allo stato del giocatore. Immagino di essere stato rovinato da questa libertà, perché con C ++ e simili mi trovo spesso a chiedermi come rendere un valore accessibile ad alcuni altri oggetti (o anche a quelli globali).
Usando l'esempio di BoxPong, cosa succede se volevo che la palla rimbalzasse sui bordi dello schermo? width e height sono proprietà della classe Game , e avrei bisogno del ball per avere accesso ad essi. Potrei passare questo tipo di valori (tramite i costruttori oi metodi in cui sono necessari), ma questo mi fa solo brutti scherzi.

Credo che il mio problema principale sia che ho bisogno che gli oggetti si conoscano, ma l'unico modo in cui posso vederlo è una gerarchia rigida, che è brutta e poco pratica.

Ho sentito parlare di "classi di amici" su C ++ e so come funzionano, ma se sono la soluzione completa, allora come mai non vedo% parole chiave% di% versato su ogni singolo C ++ progetto, e come mai il concetto non esiste in ogni lingua OOP? (Lo stesso vale per i puntatori di funzione, che ho appreso di recente.)

Grazie in anticipo per le risposte di qualsiasi tipo - e ancora una volta, se c'è una parte che non ha senso per te, fammelo sapere.

    
posta vvye 26.05.2015 - 19:30
fonte

2 risposte

7

In generale, risulta molto grave se oggetti dello stesso livello si conoscono l'un l'altro. Una volta che gli oggetti si conoscono, sono legati, o accoppiati l'uno all'altro. Ciò li rende difficili da cambiare, difficili da testare, difficili da mantenere.

Funziona molto meglio se c'è qualche oggetto "sopra" che conosce i due e può impostare le interazioni tra loro. L'oggetto che conosce i due peer può collegarli tramite l'iniezione di dipendenza o tramite eventi o tramite il passaggio di messaggi (o qualsiasi altro meccanismo di disaccoppiamento). Sì, questo porta a un po 'di una gerarchia artificiale, ma è molto meglio del pasticcio di spaghetti che si ottiene quando le cose interagiscono solo volenti o nolenti. Questo è solo più importante in C ++, dato che hai bisogno di qualcosa per possedere anche la vita degli oggetti.

Quindi, in breve, puoi farlo semplicemente avendo gli oggetti affiancati ovunque legati da un accesso ad hoc, ma è una cattiva idea. La gerarchia fornisce ordine e chiara proprietà. La cosa principale da ricordare è che gli oggetti nel codice non sono necessariamente oggetti nella vita reale (o persino nel gioco). Se gli oggetti nel gioco non formano una buona gerarchia, una diversa astrazione potrebbe essere migliore.

    
risposta data 26.05.2015 - 20:28
fonte
0

Meet BoxPong, a very simple game I made to get acquainted with object-oriented game development.

Making BoxPong helped me formulate, among other things, a fundamental question: how can I have objects that interact with each other without having to "belong" to each other?

I have quite a bit of experience writing code for the SNES, where you have access to practically the entire RAM all the time. Say you're making a custom enemy for Super Mario World, and you want it to remove all of Mario's coins, then just store zero to address $0DBF, no problem.

Sembra che manchi il punto della programmazione orientata agli oggetti.

La programmazione orientata agli oggetti riguarda la gestione delle dipendenze mediante l'inversione selettiva di determinate dipendenze chiave nell'architettura in modo da evitare rigidità, fragilità e non riusabilità.

Che cos'è la dipendenza? La dipendenza fa affidamento su qualcos'altro. Quando si memorizza zero per indirizzare $ 0DBF, si sta facendo affidamento sul fatto che quell'indirizzo è dove si trovano le monete di Mario e che le monete sono rappresentate come un numero intero. Il tuo codice nemico personalizzato dipende dal codice che implementa Mario e le sue monete. Se apporti una modifica a dove Mario memorizza le sue monete in memoria, devi aggiornare manualmente tutto il codice facendo riferimento alla posizione di memoria.

Il codice orientato agli oggetti fa in modo che il tuo codice dipenda dalle astrazioni e non dai dettagli. Quindi invece di

class Mario
{
    public:
        int coins;
}

scriverai

class Mario
{
    public:
        void LoseCoins();

    private:
        int coins;
}

Ora, se vuoi cambiare il modo in cui Mario memorizza le sue monete da un int a un long o un double o memorizzarlo sulla rete o memorizzarlo in un database o avviare un altro lungo processo, fai il resto in un unico posto: la classe Mario e tutto il tuo altro codice continua a funzionare senza modifiche.

Pertanto, quando chiedi

how can I have objects that interact with each other without having to "belong" to each other?

stai davvero chiedendo:

how can I have code that directly depends on each other without any abstractions?

che non è programmazione orientata agli oggetti.

Ti suggerisco di iniziare leggendo tutto qui: link e poi cerca su YouTube tutto per Robert Martin e guarda tutto esso.

Le mie risposte derivano da lui, e alcune sono citate direttamente da lui.

    
risposta data 26.05.2015 - 22:35
fonte

Leggi altre domande sui tag