6

Object Layer

L'Object Layer implémente les conteneurs des classes et des instances So-o et toutes les fonctions nécessaires à la classe Object.

Les types de données sont définis dans le fichier OL.h. Tout le code est dans le fichier OL.c.

  1. #include "list.h"
  2. #include "alist.h"

So-o utilise des listes simples et des listes associatives. Les fichiers list.h et alist.h déclarent les types list et alist et les fonctions pour les gérer. Le code est dans les fichiers list.c et alist.c. Il est compilé dans la librairie libso-o.a.

  1. typedef char *property;
  2. typedef char *message;
  3.  
  4. typedef union _value {
  5.     int i;
  6.     long l;
  7.     float f;
  8.     double d;
  9.     void *p;
  10. } value;
  11.  
  12. typedef value (*method)();
  13.  
  14. #define METHOD(f) (value (*)())f
  15.  
  16. typedef struct _selector {
  17.     message msg;
  18.     method func;
  19. } selector;
  20.  
  21. typedef struct _attribute {
  22.     property name;
  23.     value value;
  24. } attribute;

Une propriété ou un message est une chaîne de caractères terminée par un '\0'.

Le type de données value est une union qui sert à contenir toutes les différentes valeurs qu'une méthode peut retourner. Envoyer un message retourne toujours un type value. Pour assigner une valeur retournée par un message ou la passer à une autre fonction, utilisez le membre approprié de l'union.

Une méthode est un pointeur sur une fonction avec un type de retour value. La macro METHOD sert à transtyper une fonction qui implémente un message.

Un sélecteur associe un message à une méthode. Les propriétés d'une classe qui ont une valeur sont ses attributs.

  1. #define CLASS       'C'
  2. #define INSTANCE    'I'
  3.  
  4. typedef struct _class {
  5.     char type;
  6.     const char *name;
  7.     unsigned int revision;
  8.     struct _class *superclass;
  9.     list c_properties;
  10.     list i_properties;
  11.     alist c_messages;
  12.     alist i_messages;
  13.     alist attributes;
  14. } *class;
  15.  
  16. typedef struct _instance {
  17.     char type;
  18.     class class;
  19.     alist attributes;
  20. } *instance;

Une classe à un nom et un numéro de révision. Elle hérite son comportement d'une superclasse. Elle a des propriétés. Elle implémente des messages de classe. Les instances d'une classe ont des propriétés. Elles implémentent des messages d'instance. Une classe a ses propres attributs.

Une instance appartient à une classe. Les propriétés d'une instance qui ont une valeur sont ses attributs.

Le champ type est utilisé par l'interface pour déterminer si l'objet qui reçoit un message est une classe ou une instance. Une classe a le type CLASS. Une instance a le type INSTANCE.

La classe Object est la seule classe avec une superclasse à NULL. Toutes les autres classes héritent, pour le moins, de la classe Object.

Toutes les listes peuvent être NULL.

Le reste du fichier OL.h déclare les fonctions de l'Object Layer. Les fonctions qui commencent par class_ gèrent une classe. Les fonctions qui commencent par object_ gèrent une instance.

IMPORTANT : En principe, toutes les fonctions de l'Object Layer sont privées. Seules les fonctions de la classe Object et les fonctions de l'interface de So-o peuvent les appeler.

  1. #define CNAMEMAXLEN 64
  2. #define CNAMEREGEXP "^[:alpha:]?[[:alnum:]_-]{0,62}[:alnum:]?$"

CNAMEMAXLEN spécifie la longueur maximum d'un nom de classe. CNAMEREGEXP définit l'expression régulière utilisée pour valider un nom de classe.

  1. class class_alloc( void ) {
  2.     return (class)calloc( 1, sizeof ( struct _class ));
  3. }

class_alloc alloue l'espace nécessaire pour contenir une classe et le retourne.

  1. class class_init( class self, const char *cname, class superclass, unsigned int rev, property *c_props, property *i_props, selector *c_msgs, selector *i_msgs ) {
  2.     static regex_t regexp;
  3.  
  4.     regcomp(&regexp, CNAMEREGEXP, REG_EXTENDED | REG_NOSUB);
  5.  
  6.     if ( regexec(&regexp, cname, 0, 0, 0) != 0 )
  7.         return 0;
  8.  
  9.     extern class Object;
  10.  
  11.     self->type = CLASS;
  12.     self->name = cname;
  13.     self->revision = rev;
  14.  
  15.     self->superclass = strcmp("Object", cname) != 0 ? (superclass ? superclass : Object) : 0;
  16.  
  17.     if ( c_msgs )
  18.         class_set_class_messages(self, c_msgs);
  19.  
  20.     if ( i_msgs )
  21.         class_set_instance_messages(self, i_msgs);
  22.  
  23.     if ( c_props )
  24.         class_set_class_properties(self, c_props);
  25.  
  26.     if ( i_props )
  27.         class_set_instance_properties(self, i_props);
  28.  
  29.     return self;
  30. }

class_init initialise la définition de la classe self.

name spécifie le nom de la classe. name est validé avec l'expression régulière CNAMEREGEXP.

superclass est la référence globale de la superclasse de la nouvelle classe. Si superclass vaut 0, la nouvelle classe hérite par défaut de la classe Object définie par la variable globale Object. IMPORTANT : superclass doit contenir l'adresse de la définition d'une classe construite.

rev donne le numéro de révision de la classe. rev est un int > 0 qui peut servir à différencier des versions successives de la classe.

class_properties et instance_properties listent les propriétés de la classe et des instances de la classe. Une propriété est une chaîne de caractères terminée par un '\0'. Une liste de propriétés est un tableau terminé par un pointeur NULL. Un tableau NULL définit une liste vide.

class_messages et instance_messages sont des listes associatives de messages et de méthodes de la classe et des instances de la classe. Un message est une chaîne de caractères terminée par un '\0'. Une méthode est un pointeur sur une fonction convertie par la macro METHOD définie dans OL.h. Un sélecteur associe une méthode à un message. Une liste de messages et de méthodes est un tableau terminé par deux pointeurs NULL. Un tableau NULL définit une liste vide.

  1. class class_new( const char *name, class superclass, unsigned revision, property *class_properties, property *instance_properties, selector *class_messages, selector *instance_messages ) {
  2.     return class_init( class_alloc(), name, superclass, revision, class_properties, instance_properties, class_messages, instance_messages );
  3. }

class_new alloue l'espace nécessaire pour contenir la définition d'une classe, l'initialise et le retourne.

  1. void class_free( class self ) {
  2.     if (self->c_properties)
  3.         list_free( self->c_properties );
  4.     if (self->i_properties)
  5.         list_free( self->i_properties );
  6.     if (self->c_messages)
  7.         alist_free( self->c_messages );
  8.     if (self->i_messages)
  9.         alist_free( self->i_messages );
  10.     if (self->attributes)
  11.         alist_free( self->attributes );
  12.     free( self );
  13. }

class_free libère l'espace alloué par self, i.e. toutes les listes allouées par la classe et le conteneur de la classe. IMPORTANT : class_free ne libère pas l'espace qui a pu être alloué pour les valeurs des attributs de la classe.

  1. char *class_tostring( class self ) {
  2.     static char s[CNAMEMAXLEN+7+1];
  3.  
  4.     sprintf(s, "class(%s)", self->name);
  5.  
  6.     return s;
  7. }

class_tostring retourne une représentation textuelle de self, i.e. le mot class suivi par le nom de la classe entre parenthèses. IMPORTANT : La chaîne de caractères est formatée dans une zone statique. Il faut s'en servir avant de rappeler cette méthode.

  1. instance class_make(class self) {
  2.     return object_new( self );
  3. }

class_make retourne une nouvelle instance de self.

  1. instance object_alloc( void ) {
  2.     return (instance)calloc( 1, sizeof ( struct _instance ));
  3. }

object_alloc alloue l'espace nécessaire pour contenir une instance et le retourne.

  1. instance object_init( instance self, class c ) {
  2.     self->type = INSTANCE;
  3.     self->class = c;
  4.  
  5.     return self;
  6. }

object_init initialise la définition de l'instance self. c est la référence globale de la classe de self.

  1. instance object_new( class c ) {
  2.     return object_init(object_alloc(), c);
  3. }

object_new alloue l'espace nécessaire pour contenir la définition d'une instance, l'initialise et le retourne.

  1. void object_free( instance self ) {
  2.     if (self->attributes)
  3.         alist_free( self->attributes );
  4.     free( self );
  5. }

object_free libère l'espace alloué par self, i.e. la liste des attributs allouée par l'instance et le conteneur de l'instance. IMPORTANT : object_free ne libère pas l'espace qui a pu être alloué pour les valeurs des attributs de l'instance.

  1. instance object_copy(instance self) {
  2.     instance newself = object_new(object_class(self));
  3.  
  4.     if (self->attributes)
  5.         newself->attributes = alist_copy(self->attributes);
  6.  
  7.     return newself;
  8. }

object_copy retourne une copie de self. IMPORTANT : object_copy ne duplique pas l'espace qui a pu être alloué pour les valeurs des attributs de l'instance; self et sa copie ont des listes d'attributs indépendantes qui partagent les mêmes valeurs.

  1. char *object_tostring( instance self ) {
  2.     static char s[CNAMEMAXLEN+8+1];
  3.  
  4.     sprintf(s, "object(%s)", self->class->name);
  5.  
  6.     return s;
  7. }

object_tostring retourne une représentation textuelle de self, i.e. le mot object suivi par le nom de la classe entre parenthèses. IMPORTANT : La chaîne de caractères est formatée dans une zone statique. Il faut s'en servir avant de rappeler cette méthode.

Le reste du code implémente toutes les fonctions de l'Object Layer dont la classe Object a besoin.

class_name
Retourne le nom d'une classe.
class_revision
Retourne le numéro de révision d'une classe.
class_superclass
Retourne la superclasse d'une classe.
class_class_properties
Retourne les propriétés de classe définies par une classe.
class_instance_properties
Retourne les propriétés d'instance définies par une classe.
class_class_messages
Retourne les messages de classe définis par une classe.
class_instance_messages
Retourne les messages d'instance définis par une classe.
class_set_class_properties
Initialise les propriétés de classe d'une classe.
class_set_instance_properties
Initialise les propriétés d'instance d'une classe.
class_set_class_messages
Initialise les messages de classe d'une classe.
class_set_instance_messages
Initialise les messages d'instance d'une classe.
class_add_class_message
Ajoute un message de classe à une classe.
class_remove_class_message
Retire un message de classe à une classe.
class_add_instance_message
Ajoute un message d'instance à une classe.
class_remove_instance_message
Retire un message d'instance à une classe.
class_add_class_property
Ajoute une propriété de classe à une classe.
class_remove_class_property
Retire une propriété de classe à une classe.
class_add_instance_property
Ajoute une propriété d'instance à une classe.
class_remove_instance_property
Retire une propriété d'instance à une classe.
class_attributes
Retourne les valeurs des propriétés d'une classe.
class_set_attributes
Initialise les valeurs des propriétés d'une classe.
class_is_kind_of
Vérifie si une classe est une sous-classe d'une autre classe.
class_get
Retourne la valeur d'une propriété d'une classe.
class_set
Modifie la valeur d'une propriété d'une classe.
object_class
Retourne la classe d'une instance.
object_superclass
Retourne la superclasse d'une instance.
object_assume
Change la classe d'une instance.
object_attributes
Retourne les valeurs des propriétés d'une instance.
object_set_attributes
Initialise les valeurs des propriétés d'une instance.
object_get
Retourne la valeur d'une propriété d'une instance.
object_set
Modifie la valeur d'une propriété d'une instance.
class_find_class_property
Vérifie si une propriété de classe d'une classe existe.
class_find_instance_property
Vérifie si une propriété d'instance d'une classe existe.
class_find_class_method_class
Retourne la classe qui implémente un message de classe.
class_find_class_method
Retourne la fonction qui implémente un message de classe.
class_find_instance_method_class
Retourne la classe qui implémente un message d'instance.
class_find_instance_method
Retourne la fonction qui implémente un message d'instance.
class_send_message
Exécute un message de classe.
class_super_send_message
Exécute un message de classe hérité d'une superclasse.
object_send_message
Exécute un message d'instance.
object_super_send_message
Exécute un message d'instance hérité d'une superclasse.
VOIR AUSSI

Interface, Object

Commentaires

Votre commentaire :
[p] [b] [i] [u] [s] [quote] [pre] [br] [code] [url] [email] strip aide 2000

Entrez un maximum de 2000 caractères.
Améliorez la présentation de votre texte avec les balises de formatage suivantes :
[p]paragraphe[/p], [b]gras[/b], [i]italique[/i], [u]souligné[/u], [s]barré[/s], [quote]citation[/quote], [pre]tel quel[/pre], [br]à la ligne,
[url]http://www.izend.org[/url], [url=http://www.izend.org]site[/url], [email]izend@izend.org[/email], [email=izend@izend.org]izend[/email],
[code]commande[/code], [code=langage]code source en c, java, php, html, javascript, xml, css, sql, bash, dos, make, etc.[/code].