Interface definition prerequisites: GObject Reference Manual

## Interface definition prerequisites

To specify that an interface requires the presence of other interfaces when implemented, GObject introduces the concept of prerequisites: it is possible to associate a list of prerequisite types to an interface. For example, if object A wishes to implement interface I1, and if interface I1 has a prerequisite on interface I2, A has to implement both I1 and I2.

The mechanism described above is, in practice, very similar to Java's interface I1 extends interface I2. The example below shows the GObject equivalent:

    1
    2
    /* Make the MamanIbar interface require MamanIbaz interface. */
    G_DEFINE_INTERFACE (MamanIbar, maman_ibar, MAMAN_TYPE_IBAZ);

In the `G_DEFINE_INTERFACE` call above, the third parameter defines the prerequisite type. This is the GType of either an interface or a class. In this case the MamanIbaz interface is a prerequisite of MamanIbar. The code below shows how an implementation can implement both interfaces and register their implementations:

    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
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    static void
    maman_ibar_do_another_action (MamanIbar *ibar)
    {
      MamanBar *self = MAMAN_BAR (ibar);

      g_print ("Bar implementation of IBar interface Another Action: 0x%x.\n",
               self->instance_member);
    }

    static void
    maman_ibar_interface_init (MamanIbarInterface *iface)
    {
      iface->do_another_action = maman_ibar_do_another_action;
    }

    static void
    maman_ibaz_do_action (MamanIbaz *ibaz)
    {
      MamanBar *self = MAMAN_BAR (ibaz);

      g_print ("Bar implementation of Ibaz interface Action: 0x%x.\n",
               self->instance_member);
    }

    static void
    maman_ibaz_do_something (MamanIbaz *ibaz)
    {
      MamanBar *self = MAMAN_BAR (ibaz);

      g_print ("Bar implementation of Ibaz interface Something: 0x%x.\n",
               self->instance_member);
    }

    static void
    maman_ibaz_interface_init (MamanIbazInterface *iface)
    {
      iface->do_action = maman_ibaz_do_action;
      iface->do_something = maman_ibaz_do_something;
    }

    static void
    maman_bar_class_init (MamanBarClass *klass)
    {
      /* Nothing here. */
    }

    static void
    maman_bar_init (MamanBar *self)
    {
      self->instance_member = 0x666;
    }

    G_DEFINE_TYPE_WITH_CODE (MamanBar, maman_bar, G_TYPE_OBJECT,
                             G_IMPLEMENT_INTERFACE (MAMAN_TYPE_IBAZ,
                                                    maman_ibaz_interface_init)
                             G_IMPLEMENT_INTERFACE (MAMAN_TYPE_IBAR,
                                                    maman_ibar_interface_init))

It is very important to notice that the order in which interface implementations are added to the main object is not random: `g_type_add_interface_static`, which is called by `G_IMPLEMENT_INTERFACE`, must be invoked first on the interfaces which have no prerequisites and then on the others.