Progettazione: richiamo alla classe genitore

11

Quando si modella un oggetto con i bambini è comune includere i bambini tramite la composizione, come membro della classe genitore. A volte però i bambini hanno bisogno di dire qualcosa ai genitori, hanno bisogno di chiamare una funzione del genitore. Come può essere realizzato usando C ++? Alcune opzioni sono:

  1. Rendi globale la classe genitore, quindi gli oggetti figli saranno in grado di chiamare le funzioni membro dell'oggetto padre.

  2. Inietti l'oggetto genitore come un puntatore o riferimento in ogni oggetto figlio. Quindi, quando il bambino ha bisogno di dire qualcosa all'oggetto genitore, può sempre farlo perché ha una variabile membro che può usare.

Quali sono gli altri metodi per farlo? C'è un modello di progettazione generale o un nome per questo genere di cose?

Nota che sono interessato a idee e soluzioni in C ++ perché i dettagli saranno diversi in altri linguaggi orientati agli oggetti. Ad esempio, il punto 2 sopra menziona "puntatori o riferimenti" ed entrambi sono possibili solo in C ++. C ++ ha caratteristiche linguistiche che non sono presenti in altri linguaggi, quindi implementazioni di una soluzione al problema potrebbero incorporare queste caratteristiche linguistiche che rendono la soluzione diversa da quella che qualcuno potrebbe trovare in un'altra lingua.

    
posta sashang 22.05.2012 - 14:36
fonte

7 risposte

13

Per prima cosa, questo può essere un odore di codice. Il punto di utilizzo della composizione per il genitore / figlio è che il genitore conosce i bambini ma non viceversa. Soprattutto se la relazione è più di un 'contiene' di 'è composto da'.

Un riferimento al genitore è possibile e abbastanza comune in C ++. In altre lingue, un oggetto o evento di funzione è più spesso usato per consentire al bambino di comunicare cose che gli estranei potrebbero voler sapere. Questo è un ordinario modello di abbonamenti alla pubblicazione. Sospetto che ciò che è più idiomatico dipenda dalla versione del C ++ che stai usando e dagli standard del tuo codebase.

    
risposta data 22.05.2012 - 15:31
fonte
2

Quello che puoi fare è mantenere un riferimento al genitore nella classe figlia, per composizione. In questo modo, il bambino conosce il suo genitore e può invocare metodi pubblici su di esso.

Quindi andrei con l'opzione 2. Bisogna fare attenzione però, quando un figlio viene rimosso dal genitore, è necessario rimuovere il riferimento al genitore nel figlio e puntarlo su null (o un nuovo genitore, se ne ha uno). Oppure puoi semplicemente cancellare l'oggetto figlio, a seconda del contesto.

    
risposta data 22.05.2012 - 14:42
fonte
2

Come altri hanno sottolineato, l'idea di base di iniettare l'oggetto genitore come un puntatore o riferimento è la strada da percorrere - in linea di principio.

Questo ha uno svantaggio: si ottiene una dipendenza ciclica tra il genitore e il figlio. Se si desidera evitare ciò, definire una classe base astratta (un'interfaccia) IParent da cui eredita il genitore. IParent dovrebbe contenere i metodi come funzioni virtuali che il bambino vuole chiamare. Quindi, iniettare il genitore come riferimento a IParent . Ciò rende l'unità testare il bambino molto più facilmente, poiché ora puoi sostituire facilmente l'oggetto genitore con un oggetto fittizio.

Se il tuo bambino ha bisogno di chiamare solo una funzione del tuo oggetto genitore, una classe IParent completa potrebbe essere sovradimensionata. In questo caso, sarà sufficiente iniettare un puntatore alla funzione membro nel child o un oggetto functor che incapsula quella funzione membro.

    
risposta data 22.05.2012 - 20:34
fonte
1

Passagli un riferimento o un puntatore al genitore. Puoi renderli amici del genitore o rendere pubblico il metodo chiamato. Se non vuoi fare nulla di quanto sopra, puoi passare loro un oggetto "ponte" che espone uno dei metodi del genitore come pubblico ed è esso stesso una classe nidificata prive del genitore (quindi ha accesso a ogni metodo genitore ). Questo può essere un po 'troppo complesso in molte situazioni, tuttavia.

    
risposta data 22.05.2012 - 14:41
fonte
1

2) Inject the parent object as a, pointer or reference, into every child object. Then when the child needs to tell the parent object something, it can always do so because it has a member variable that it can use.

È un'opzione perfettamente valida. Tutte le lingue moderne hanno una funzione che può essere utilizzata per fare riferimento a un'altra lingua.

    
risposta data 22.05.2012 - 15:39
fonte
0

Nota questo è c # specifico. Non so se c ++ ha qualcosa di simile.

Se hai un gui-form con i pulsanti di solito hai un approccio diverso usando Event-Subscribtion noto anche come Observer_pattern o modello di abbonamento-pubblicazione .

Il pulsante di solito non conosce la forma specifica in cui vive. Invece il pulsante attiva o pubblica un evento e il modulo riceve una notifica sottoscritto e può reagire di conseguenza.

Oltre a gui-s, questo meccanismo può essere utilizzato in ogni relazione paren-child

    
risposta data 22.05.2012 - 15:30
fonte
0

Esiste un approccio simile con leggere variazioni ma che offre vantaggi:

Dire che il genitore A contiene il componente C

Nel componente C, dichiara InterfaceC e tieni il riferimento ad esso. Questa è l'interfaccia del componente con il mondo esterno.

Parent A implementa InterfaceC e imposta il suo riferimento in Component C. Il componente C vede Parent A come InterfaceC.

L'idea è: un componente parla all'esterno usando la sua interfaccia.

I vantaggi dell'utilizzo di questa impostazione rispetto all'impostazione diretta del genitore sono:

Dire che il componente fa qualcosa e ha bisogno di notificare il genitore. Chiama l'interfaccia. Più tardi, decidi di voler cambiare il genitore. Al componente non interessa affatto e non cambierai nulla.

In seguito, si desidera notificare molti oggetti di un evento. È sufficiente creare un elenco di InterfaceC e aggiungere riferimenti ad esso.

Svantaggi: una classe genitore finirà per implementare molte interfacce (penso comunque che sia un vantaggio, dato che guardando la dichiarazione della classe, so immediatamente chi ci parla)

    
risposta data 06.12.2018 - 20:48
fonte

Leggi altre domande sui tag