|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Présentation BOOPSI est l'abréviation de "Basic Object Oriented Programming System for Intuition" c'est-à-dire "Système de programmation orienté objet pour intuition". Il permet entre autres :
Ainsi, buttongclass hérite de gadgetclass, qui elle-même hérite de rootclass. En nomenclature BOOPSI, gadgetclass est une superclasse (classe parent) de buttongclass. Il est à remarquer que la notion d'héritage multiple (grâce à laquelle une classe peut hériter de plusieurs autres à la fois) n'existe pas avec BOOPSI. 2. Les objets BOOPSI 2.a Création d'un objet Un objet BOOPSI résulte de l'instantiation d'une classe existante publique ou privée. Cette création se réalise par l'intermédiaire des fonctions :
Le pointeur sur Class, dans le cas d'une classe privée est fourni au moment de la déclaration de cette dernière (Cf. paragraphe 3.b). Exemple :
2.b Destruction de l'objet Pour détruire un objet, il suffit d'utiliser la procédure :
Exemple : DisposeObject(mystringgadget); 2.c Attributs Un objet se compose de deux parties distinctes :
ULONG GetAttr (ULONG attrID, APTR myobject, ULONG *mydata); ...où "attrID" est l'identificateur de l'attribut, "myobject" est l'objet BOOPSI source, "mydata" l'adresse de la variable dans laquelle on veut stocker la valeur de l'attribut attrID. ULONG SetAttrs(APTR myobject, Tag1, Value1, ...); ...où "myobject" est l'objet BOOPSI destination, suivi par la liste des attributs/valeurs, ce qui permet de positionner plusieurs attributs. Dans le cas d'un objet de type gadget, il est nécessaire de passer plus d'informations en paramètre, d'où l'utilisation de la fonction :
2.d Méthodes Toute action sur un objet BOOPSI s'effectue par l'envoi d'un message vers celui-ci. Ce message décrit la méthode qui doit être appliquée sur l'objet et passe les arguments nécessaires à son exécution. Dans les paragraphes précédents, chaque fonction présentée correspond à l'exécution d'une méthode héritée de la classe racine "rootclass". Ainsi, NewObject() envoie une méthode OM_NEW, DisposeObject(): OM_DISPOSE, SetAttrs(): OM_SET, GetAttrs(): OM_GET. D'autres méthodes existent, spécifiques aux différentes classes. Pour les appliquer, il suffit d'utiliser l'une des deux fonctions de amiga.lib :
Une méthode retourne toujours un ULONG (entier non signé sur 32 bits), qui peut être, suivant les cas, une valeur entière ou un pointeur sur un objet. En règle générale, un retour nul équivaut à un échec. Exemple : SetAttrs(myobject, myattribute, myvalue) Peut être réalisé par l'appel suivant :
3. Création d'une classe BOOPSI 3.a Structure d'une classe Créer une telle classe est particulièrement aisé. Elle se compose en fait de deux parties distinctes: d'une structure de données correspondant aux attributs de l'objet, et d'une fonction principale ClassDispatcher(Class *class, Object *object, Msg msg); qui reçoit les méthodes et réagit en fonction de la valeur de celles-ci. La classe a donc l'allure suivante :
3.b Initialisation/Libération d'une classe Lors de la création d'une classe, on doit fournir entre autres : son nom dans le cas où elle est destinée à être publique, le nom de son parent, ainsi que la taille des données qu'elle gère. On lui fournit ces renseignements lors de son initialisation, à l'appel de la fonction :
Si cette classe est publique, newclassID est une chaîne la nommant (NULL si privée) ; les deux champs suivants nomment la classe parente (publique ou privée suivant les cas) ; instancesize donne la taille de l'espace de données qui devra être fourni à chaque objet ; flags (drapeaux) est toujours nul. Ensuite, on initialise les champs de la structure Class de manière à lui indiquer quelle est notre fonction de Dispatch des méthodes. Remarques :
3.c Méthodes fondamentales En règle générale, tout objet doit au moins gérer certaines des méthodes de la classe racine (rootclass), à savoir OM_NEW, OM_SET, OM_GET, OM_DISPOSE. Nous allons donc nous attacher à décrire chacune de ces méthodes et les arguments qu'elles utilisent. Avant toute chose, il est nécessaire de connaître la fonction DoSuperMethodA(Class *cl, Object *trueclass, Msg msg) de amiga.lib qui applique la méthode à la classe parente. Cette fonction doit être appelée de manière systématique pour les méthodes gérées par les classes parentes, de manière à ce que le traitement soit complet. OM_NEW : cette méthode est appelée lors de la création de l'objet (fonction NewObject()). Elle doit, dans l'ordre :
OM_SET : le but de cette méthode est de mettre à jour les valeurs des attributs de l'objet. Elle est appelée lors de l'utilisation des fonctions SetAttrs() et SetGadgetAttrs() et reçoit, comme OM_NEW, une structure opSet en paramètre. Dans le cas où l'objet est un gadget, ops_GInfo est un pointeur sur une structure GadgetInfo, et est indéfini dans le cas contraire. Votre rôle est de parcourir la liste des attributs et de les positionner un à un (une utilisation judicieuse de la fonction NextTagItem() de la utility.library peut être utile !). OM_GET : requête pour obtenir la valeur d'un attribut de l'objet. Cette méthode est appliquée lors de l'utilisation de la fonction SetAttrs(). Elle reçoit en paramètre un message (<intuition/classusr.h>) :
Vous devez vérifier que l'attribut opg_AttrID existe, le renvoyer si c'est le cas, le passer à la superclasse dans le cas contraire. OM_DISPOSE : méthode appliquée à la libération de l'objet. Effectuez les libérations mémoires nécessaires et passez le message à la superclasse. OM_NOTIFY : en général traité par une classe parent. Vous devez juste appeler la fonction Dispatcher de la superclasse. Pour finir, voici d'autres méthodes de rootclass :
J'imagine que l'ensemble de l'article doit paraître obscur, en particulier à ceux qui ne sont pas habitués à la programmation objet. Pour les autres, vous remarquerez qu'il s'agit en fait d'une implantation dynamique du concept d'objets, certes moins complète que ce que proposent des langages dédiés, mais tout de même fort intéressante pour les programmeurs C que nous sommes ! Dans le prochain article, vous aurez le droit à un (superbe !) exemple qui illustrera tous ces propos.
|