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.
- #include "list.h"
- #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.
- typedef char *property;
- typedef char *message;
- typedef union _value {
- int i;
- long l;
- float f;
- double d;
- void *p;
- } value;
- typedef value (*method)();
- #define METHOD(f) (value (*)())f
- typedef struct _selector {
- message msg;
- method func;
- } selector;
- typedef struct _attribute {
- property name;
- value value;
- } 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.
- #define CLASS 'C'
- #define INSTANCE 'I'
- typedef struct _class {
- char type;
- const char *name;
- unsigned int revision;
- struct _class *superclass;
- list c_properties;
- list i_properties;
- alist c_messages;
- alist i_messages;
- alist attributes;
- } *class;
- typedef struct _instance {
- char type;
- class class;
- alist attributes;
- } *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.
- #define CNAMEMAXLEN 64
- #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.
- class class_alloc( void ) {
- return (class)calloc( 1, sizeof ( struct _class ));
- }
class_alloc
alloue l'espace nécessaire pour contenir une classe et le retourne.
- 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 ) {
- static regex_t regexp;
- regcomp(®exp, CNAMEREGEXP, REG_EXTENDED | REG_NOSUB);
- if ( regexec(®exp, cname, 0, 0, 0) != 0 )
- return 0;
- extern class Object;
- self->type = CLASS;
- self->name = cname;
- self->revision = rev;
- self->superclass = strcmp("Object", cname) != 0 ? (superclass ? superclass : Object) : 0;
- if ( c_msgs )
- class_set_class_messages(self, c_msgs);
- if ( i_msgs )
- class_set_instance_messages(self, i_msgs);
- if ( c_props )
- class_set_class_properties(self, c_props);
- if ( i_props )
- class_set_instance_properties(self, i_props);
- return self;
- }
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.
- class class_new( const char *name, class superclass, unsigned revision, property *class_properties, property *instance_properties, selector *class_messages, selector *instance_messages ) {
- return class_init( class_alloc(), name, superclass, revision, class_properties, instance_properties, class_messages, instance_messages );
- }
class_new
alloue l'espace nécessaire pour contenir la définition d'une classe, l'initialise et le retourne.
- void class_free( class self ) {
- if (self->c_properties)
- list_free( self->c_properties );
- if (self->i_properties)
- list_free( self->i_properties );
- if (self->c_messages)
- alist_free( self->c_messages );
- if (self->i_messages)
- alist_free( self->i_messages );
- if (self->attributes)
- alist_free( self->attributes );
- free( self );
- }
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.
- char *class_tostring( class self ) {
- static char s[CNAMEMAXLEN+7+1];
- sprintf(s, "class(%s)", self->name);
- return s;
- }
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.
- instance class_make(class self) {
- return object_new( self );
- }
class_make
retourne une nouvelle instance de self
.
- instance object_alloc( void ) {
- return (instance)calloc( 1, sizeof ( struct _instance ));
- }
object_alloc
alloue l'espace nécessaire pour contenir une instance et le retourne.
- instance object_init( instance self, class c ) {
- self->type = INSTANCE;
- self->class = c;
- return self;
- }
object_init
initialise la définition de l'instance self
.
c
est la référence globale de la classe de self
.
- instance object_new( class c ) {
- return object_init(object_alloc(), c);
- }
object_new
alloue l'espace nécessaire pour contenir la définition d'une instance, l'initialise et le retourne.
- void object_free( instance self ) {
- if (self->attributes)
- alist_free( self->attributes );
- free( self );
- }
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.
- instance object_copy(instance self) {
- instance newself = object_new(object_class(self));
- if (self->attributes)
- newself->attributes = alist_copy(self->attributes);
- return newself;
- }
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.
- char *object_tostring( instance self ) {
- static char s[CNAMEMAXLEN+8+1];
- sprintf(s, "object(%s)", self->class->name);
- return s;
- }
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.
Commentaires