[LINUX] Considérez une représentation «semblable» orientée objet facile à utiliser en C. ~ Remplacement de l'interface de la partie 2

0/2 Introduction void * 1/2 Expression de classe et héritage 1/2 2018/07/01 Réexamen Réexamen: expression de classe et héritage 2/2 Interface, Override ← Ici

Cette fois, c'est une classe d'interface et un remplacement. Honnêtement, après avoir écrit Realization of Interface Class Il y a une partie qui est profondément orientée objet parce que je veux écrire mon histoire préférée pour être décrite cette fois.

Le concept et la méthode d'implémentation du langage C et de la classe d'interface sont communs! C'est une impression.

** Qu'est-ce qu'une classe d'interface **

Définissez uniquement la méthode et laissez la classe d'implémentation à chacun. Il est pratique pour l'utilisateur de modifier le comportement en sélectionnant la classe d'implémentation.

Grosso modo en langage C,

Classe d'interface ⇒ Définition API de la bibliothèque dynamique Classe d'implémentation ⇒ Corps de bibliothèque dynamique

n'est-ce pas. La différence est que vous pouvez en avoir plus d'un.

** À propos de l'utilité de la représentation de classe d'interface en langage C **

En tant que méthode de réalisation, [représentation de la méthode publique précédente](https://qiita.com/developer-kikikaikai/items/ee782a4865d9186c5d8c#%E3%82%AF%E3%83%A9%E3%82%B9%E3 Écrit en% 82% 92% E3% 81% A9% E3% 81% 86% E8% A1% A8% E7% 8F% BE% E3% 81% 99% E3% 82% 8B% E3% 81% 8B) Je vais l'omettre, Comme mentionné ici ** Lors de l'appel d'une méthode de classe en C, si vous utilisez this, vous devez la passer en argument ** J'ai écrit.

Ensuite, si vous pensez à implémenter de nombreuses classes d'implémentation de classe d'interface, Que ce soit pour exprimer l'API comme une API publique ou comme une classe d'interface avec un pointeur de fonction est assez différent.

Faisons-le car cela peut être fait simplement avec la classe d'interface! Cependant, c'est un gaspillage si c'est le même que le système existant. Alors quel type de cas est efficace?

** Cas 1: lorsque la personne qui utilise réellement l'interface n'a pas du tout besoin de connaître la substance **

Par exemple, dans un système où des modules avec la même interface sont ajoutés ou supprimés, vous pouvez créer une classe de gestion sans informer l'utilisateur de la classe d'implémentation de l'interface. Dans un tel cas, il est logique d'introduire une classe d'interface en langage C. L'exemple écrit dans [Realization of interface class](https://qiita.com/developer-kikikaikai/items/47f92acbc0a19172b6d4:'interface class ') est comme ça.

L'enquêteur reçoit les informations des personnes à interroger comme une classe d'interface et pose des questions fixes une par une. L'enquêteur n'a qu'à répondre aux questions, c'est donc comme laisser la gestion de la personne à interroger à une autre personne.

Organisez et expliquez le code. Tout d'abord, définissez une classe d'interface appelée culture_if.

culture.h


struct culture_if {
        char *(*introduce)();//Auto-introduction
        char *(*get_name)();//Nom
        char *(*answer)(int id);//Question
};

Ensuite, définissez une API publique appelée la classe people_manager.

people_manager.h


#include "culture_if"
void * people_manager_new();
int people_manager_get_any_people(void *, struct culture_if *peoples);
void * people_manager_free(void *);

New la classe d'implémentation culture_if de ceux qui sont venus aujourd'hui quand people_manager était nouveau, Utilisez people_manager_get_any_people pour passer la liste.

Donc, la mise en œuvre de l'intervieweur ressemble à ceci.

main.c


#include <stdio.h>
#include "people_manager.h"
#include "culture_if"

int main() {
	struct {
		int id;
		char * question;
	} questions[] =
	{
		{FOOD, FOOD_QUESTION},
		{HAPPY, HAPPY_QUESTION},
		{CONPUTER, CONPUTER_QUESTION},
	};

	struct culture_if max_members[10];
	void * people_manager = people_manager_new();
	int member_num = people_manager_get_any_people(max_members);

	printf("[Interviewer]Bonjour à tous. J'ai hâte de travailler avec vous aujourd'hui. Tout d'abord, veuillez vous présenter brièvement.\n");

	int i=0;
	for( i = 0 ; i < member_num; i ++ ) {
		printf("  [%Auto-introduction de la personne dth]\n", i+1);
		printf("\t%s\n", max_members[i].introduce() );
	}

	printf("\n");
	printf("[Interviewer]Merci beaucoup. Ensuite, j'aimerais poser les questions une par une.\n N'hésitez pas à répondre.\n\n");

	int j=0;
	for ( i = 0 ; i < sizeof(questions)/sizeof(questions[0]); i ++ ) {
		printf("Q %d: %s\n", i+1, questions[i].question);
		for( j = 0 ; j < member_num ; j ++ ) {
			printf("  [A:%s]\n", max_members[i].get_name());
			printf("\t%s\n", max_members[i].answer(i));
		}
		printf("\n");
	}

	printf("[Interviewer]Cela conclut la question. Merci tout le monde!\n");
	people_manager_free(people_manager);
	return 0;
}

Avec cela, même si la personne à interroger change, la mise en œuvre du côté de l'intervieweur peut être conservée telle quelle. Ce type d'utilisation n'est-il pas bon?

** Cas 2: Ajouter un plug-in de bibliothèque statique avec dlopen **

Est-ce uniquement pour Linux? Il existe une fonction standard appelée dlopen / dlsym.

dlfcn.h


#include <dlfcn.h>
void *dlopen(const char *filename, int flag);
void *dlsym(void *handle, const char *symbol);

Extrait de manpage.

En bref, si vous spécifiez le fichier de bibliothèque avec dlopen puis spécifiez le nom de la fonction avec dlsym, vous obtiendrez le pointeur de fonction correspondant à la fonction. Après cela, la fonction de la bibliothèque peut être exécutée à l'aide du pointeur de fonction. C'est un mécanisme existant, mais c'est exactement l'idée d'une classe d'interface.

En fait, comment l'utiliser comme classe d'implémentation d'interface est comme ceci

  1. Définissez un pointeur de fonction qui sera une classe d'interface. Allons-y avec culture.h.
  2. Déterminez chaque méthode de la classe d'interface et le nom d'API correspondant.
  3. Chargez la bibliothèque qui implémente les 3 API ci-dessus avec dlopen et définissez-la sur la culture_if correspondante avec dlsym.

Par exemple, choisissez le nom comme suit et demandez à la personne en charge de l'implémentation de l'interface d'implémenter chaque API et d'en faire une bibliothèque. --void (* introduire) () void culture_if_introduce ();// Auto-introduction --char * (* get_name) ()void culture_if_get_name ();// Nom --char * (* answer) (int id)void culture_if_answer ();// Question

Si vous le pouvez, chargez chaque bibliothèque avec dlopen et les méthodes de la classe d'implémentation d'interface sont terminées.

python


struct culture_if * culture_if_new( chhar * lname /*"Nom du fichier de la bibliothèque"*/) {
    void * handle = dlopen(lname , flag);
    struct culture_if * culture_if = malloc(sizeof(struct culture_if ));

    culture_if->introduce = dlsym(handle, "culture_if_introduce");
    culture_if->get_name= dlsym(handle, "culture_if_get_name");
    culture_if->answer= dlsym(handle, "culture_if_answer");
    return culture_if;
}

La bonne chose à ce sujet est que le nom de la méthode du côté de la classe d'implémentation peut également être corrigé et que la logique du côté de la gestion est également décidée. Si cela est bien fait, vous pouvez augmenter le nombre de classes d'implémentation d'interface sans toucher au côté gestion. Peut-être que l'OSS commun avec des connecteurs supplémentaires ressemble à ceci.

Je suis absolument accro à certains modèles de conception, donc je pense que je vais bientôt faire un échantillon.

** Représentation de classe d'interface en langage C Résumé **

passer outre

En langage C, les pointeurs de fonction étaient utilisés pour représenter les interfaces. Cela signifie qu'il est très facile de passer outre. Remplacez simplement le pointeur.

Donc, si vous définissez la méthode publique avec les remplacements à l'esprit, il est préférable d'utiliser un pointeur de fonction. L'échantillon est omis car il suffit de l'écraser.

** Impression **

C'est l'impression que j'écris depuis longtemps dans le 0-2.

Je ne suis pas bon dans ce domaine, et certaines parties ne sont pas écrites dans le langage orienté objet lui-même, La conception orientée objet peut être effectuée correctement même en langage C si vous utilisez la méthode d'expression alternative! Telle est mon impression.

Ça fait longtemps, mais c'est tout.

Recommended Posts

Considérez une représentation «semblable» orientée objet facile à utiliser en C. ~ Remplacement de l'interface de la partie 2
Considérez si la programmation était un anime en Python et C
Réaliser une classe d'interface en langage C