inheritance

Inheritance in SSTS is interesting, it follows the same paradigm as GObject .

Header file

In the header file the structs that will define the object are difened along with the functions that operate on the object.

Foo.h


#ifndef __H_FOO__
#define __H_FOO__

#include "baseobject.h"
#include <stdbool.h>
typedef struct _FooClass FooClass;
typedef struct _Foo Foo;
typedef struct _FooPrivate FooPrivate; //the private data is defined in the .c file

struct _FooClass {
  SBaseObjectClass parent_class; // The parent class holds the methods of the object
  CompFunc some_method; // Some method associated with the object.
};

struct _Foo {
  SBaseObjectInstance parent;
  FooPrivate * priv;
};
    

This was the declaration of the the data structures.

Then we need some functions to operate on the objects:


Foo * foo_new (char * my_str);
void foo_free (Foo * self);
bool foo_comp (Foo * self, char * other_str);
void foo_set_str (Foo * self, char * new_str);

#endif //__H_FOO__
    

C-Code file

In the .c file we define the real functions and methods to be used with the object. It is a littl fidely at first but when the objet is in place it should be ready to use.

Remeber, never trust anyone elses code.

Foo.c


#include "Foo.h"

struct _FooPrivate {
  char * my_str; //The private data.
};

void foo_deinit_method (Foo * self); // Prototype the deinit method.
void foo_to_string_method (Foo * self); // Prototype the to_string method.
bool foo_comp_method (char * str1, char * str2); // Prototype the comp method

//The constructor
Foo * foo_new (char * my_str) {
  Foo * self = malloc ( sizeof (Foo));
  FooClass * klass = malloc( sizeof (FooClass));
  
  s_base_object_set_class (self, klass);
  s_base_object_initize (self);
  s_base_object_set_deinit_method (self, foo_deinit_method);
  s_base_object_set_to_string_method (self, foo_to_string_method);
  klass->some_method = foo_comp_method;
  
  return self;
}

void foo_free (Foo * self) {
  s_base_object_free (self); // Calls foo_deinit_method
}

bool foo_comp (Foo * self, char * other_str) {
  FooClass * klass = (FooClass *) s_base_object_get_class (self);
  return klass->some_method (self->priv->my_str, other_str);
}

void foo_set_str (Foo * self, char * new_str) {
  free (self->priv->my_str);
  self->priv->my_str = s_string_new (new_str);
}

    

Now we are almost done, the only things that remain is to write the methods. but first we have to go through what the code does.

In the constructor foo_new we first create a pointer to an instance of the object and an instance of the object class. The class is then set to the object instance using the s_base_object_set_class function. It is important to set the objects class before you initize the object.

After the class is set the object is initized, this adds the standard deinit, ref, unref and to_string methods.

We then have to set our own to_string and deinit methods using the s_base_object_set_to_string_method, and s_base_object_set_deinit_method .

In the start of the C-file we wrote some prototypes or declarations of these methods, now it is time to implement them.


void foo_deinit_method (Foo * self) {
  FooClass klass = (FooClass *) s_base_object_get_class (self);
  free(self->priv->my_str);
  free(klass);
  free(self);
}

void foo_to_string_method (Foo * self) {
  return self->priv->my_str;
}

bool foo_comp_method (char * str1, char * str2) {
  if ( strcmp ( str1, str2 ) == 0 ) {
    return true;
  } else {
    return false;
  }
}
    

And that is it.

Please note that not any of the objects in the system are thread-safe, and probably never will be.