web-dev-qa-db-fra.com

Conception: retour à la classe des parents

Lors de la modélisation d'un objet avec des enfants, il est courant d'inclure les enfants via la composition, en tant que membre de la classe mère. Parfois, cependant, les enfants doivent dire à la parente quelque chose, ils doivent appeler une fonction du parent. Comment cela peut-il être accompli en utilisant c ++? Certaines options sont:

  1. Rendre la classe des parents globale, donc les objets enfants pourront appeler des fonctions membres de l'objet parent.

  2. Injectez l'objet parent en tant que pointeur ou référence, dans chaque objet enfant. Ensuite, lorsque l'enfant doit indiquer à l'objet parent quelque chose, il peut toujours le faire, car il a une variable de membre qu'elle peut utiliser.

Quelles sont les autres méthodes de faire cela? Y a-t-il un modèle de conception général ou un nom pour ce genre de chose?

Notez que je suis intéressé par des idées et des solutions en C++, car les détails seront différents dans d'autres langues orientées objet. Par exemple, le point 2 ci-dessus mentionne les "pointeurs ou références" et les deux ne sont possibles que dans C++. C++ a des caractéristiques linguistiques qui ne sont pas présentes dans d'autres langues par conséquent, la mise en œuvre d'une solution au problème incorporera potentiellement ces fonctionnalités linguistiques, ce qui différencie la solution différente de ce que quelqu'un pourrait venir dans une autre langue.

13
sashang

Tout d'abord, cela peut être une odeur de code. Le point d'utilisation de la composition pour les parents/enfants est que le parent connaît les enfants mais pas vice versa. Surtout si la relation est davantage une "contient" que "est composée de".

Une référence au parent est possible et assez courante en C++. Dans d'autres langues, un objet de fonction ou un événement est plus souvent utilisé pour permettre à l'enfant de communiquer des choses que les étrangers voudront peut-être savoir. Ceci est un modèle de motif commun de publication-abonné. Je soupçonne que ce qui est plus idiomatique dépend de la version de C++ que vous utilisez et des normes de votre code de code.

16
Telastyn

Comme d'autres l'ont souligné, l'idée de base de l'injection de l'objet parent comme un pointeur ou une référence est la voie à suivre en principe.

Cela a un inconvénient: vous obtenez une dépendance cyclique entre le parent et l'enfant. Si vous souhaitez éviter cela, définissez une classe de base abstraite (une interface) IParent à partir de laquelle votre parent hérite. IParent doit contenir les méthodes comme des fonctions virtuelles que l'enfant veut appeler. Ensuite, injectez le parent comme référence à IParent. Cela rend l'unité à tester beaucoup l'enfant plus facile, car vous pouvez maintenant remplacer facilement l'objet parent par un objet simulé.

Si votre enfant doit appeler une seule fonction de votre objet parent, une classe IParent peut être surdimensionnée. Dans ce cas, il suffira d'injecter un pointeur à la fonction de membre dans l'enfant ou d'un objet de foncteur encapsulant cette fonction membre.

3
Doc Brown

Il y a une approche similaire avec une légère variation mais qui donne des avantages:

Dire parent a contient un composant C.

Dans le composant c, déclarez interfacecec et y reformez-vous. Ceci est l'interface du composant avec le monde extérieur.

Parent Un interfaceCeci implémente et définit sa référence dans le composant C. Component C voit le parent A comme interfaceC.

L'idée est la suivante: un composant parle à l'extérieur à l'aide de son interface.

Les avantages de l'utilisation de cela sur la définition du parent directement sont les suivants:

Dites que le composant fait quelque chose et qu'il doit notifier le parent. Il appelle l'interface. Plus tard, vous décidez que vous voulez changer le parent. Le composant ne se soucie pas du tout et vous ne changerez aucun changement.

Dites plus tard, vous voulez informer de nombreux objets d'un événement. Vous créez simplement une liste d'interfacec et d'y ajouter des références.

Inconvénients: une classe parentale finira par mettre en œuvre de nombreuses interfaces (j'en pense comme un avantage, car en regardant la déclaration de classe, je sais immédiatement qui lui parle)

1
Makketronix

Transmettez-leur une référence ou un pointeur vers le parent. Vous pouvez leur faire des amis du parent, ou faire la méthode appelée publique. Si vous ne voulez pas faire de ce qui précède, vous pouvez leur transmettre un objet "Bridge" qui expose l'une des méthodes du parent comme publique et est elle-même une classe nichée proprement imbriquée du parent (par conséquent, il a accès à chaque méthode des parents. ). Cela peut être un peu trop complexe dans de nombreuses situations.

1
quant_dev

2) Injectez l'objet parent en tant que pointeur ou référence, dans chaque objet enfant. Ensuite, lorsque l'enfant doit indiquer à l'objet parent quelque chose, il peut toujours le faire, car il a une variable de membre qu'elle peut utiliser.

Est une option parfaitement viable. Toutes les langues modernes ont une fonctionnalité qui peut être utilisée pour se référer à une autre langue.

1
DeadMG