Implementing interfaces

Once the interface is defined, implementing it is rather trivial.

The first step is to define a normal final GObject class exactly as in the section called “Boilerplate header code”.

The second step is to implement ViewerFile by defining it using G_DEFINE_TYPE_WITH_CODE and G_IMPLEMENT_INTERFACE instead of G_DEFINE_TYPE:

1
2
3
4
5
static void viewer_file_editable_interface_init (ViewerEditableInterface *iface);

G_DEFINE_TYPE_WITH_CODE (ViewerFile, viewer_file, G_TYPE_OBJECT,
                         G_IMPLEMENT_INTERFACE (VIEWER_TYPE_EDITABLE,
                                                viewer_file_editable_interface_init))

This definition is very much like all the similar functions seen previously. The only interface-specific code present here is the use of G_IMPLEMENT_INTERFACE.

Classes can implement multiple interfaces by using multiple calls to G_IMPLEMENT_INTERFACE inside the call to G_DEFINE_TYPE_WITH_CODE

viewer_file_editable_interface_init, the interface initialization function: inside it every virtual method of the interface must be assigned to its implementation:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
static void
viewer_file_editable_save (ViewerFile  *self,
                           GError     **error)
{
  g_print ("File implementation of editable interface save method: %s.\n",
           self->filename);
}

static void
viewer_file_editable_undo (ViewerFile *self,
                           guint       n_steps)
{
  g_print ("File implementation of editable interface undo method: %s.\n",
           self->filename);
}

static void
viewer_file_editable_redo (ViewerFile *self,
                           guint       n_steps)
{
  g_print ("File implementation of editable interface redo method: %s.\n",
           self->filename);
}

static void
viewer_file_editable_interface_init (ViewerEditableInterface *iface)
{
  iface->save = viewer_file_editable_save;
  iface->undo = viewer_file_editable_undo;
  iface->redo = viewer_file_editable_redo;
}

static void
viewer_file_init (ViewerFile *self)
{
  /* Instance variable initialisation code. */
}

If the object is not of final type, e.g. was declared using G_DECLARE_DERIVABLE_TYPE then G_ADD_PRIVATE macro should be added. The private structure should be declared exactly as for a normal derivable object, see the section called “Boilerplate code”.

1
2
3
4
G_DEFINE_TYPE_WITH_CODE (ViewerFile, viewer_file, G_TYPE_OBJECT,
                         G_ADD_PRIVATE (ViewerFile)
                         G_IMPLEMENT_INTERFACE (VIEWER_TYPE_EDITABLE,
                                                viewer_file_editable_interface_init))