[glib] Fix up GObject interface documentation
- From: Stefan Walter <stefw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib] Fix up GObject interface documentation
- Date: Mon, 9 Jul 2012 15:55:52 +0000 (UTC)
commit 3b0f1cc432b546c538d82036bd1a655489d11f35
Author: Stef Walter <stefw gnome org>
Date: Sat May 5 12:51:16 2012 +0200
Fix up GObject interface documentation
* Document how to override interfaces already implemented
in a base class, and also call those base class implementations
from a derived reimplementation.
* Don't recomend people use base_init() style functions to
initialize interface signals and properties, use default_init()
aka class_init() instead (as G_DEFINE_INTERFACE() uses).
* The above solves the interface init called multiple times
problem, so remove some needless naysaying about that.
* Document default_init() in the interface initialization discussion
* Linkify more stuff.
* Remove some crud and typos
https://bugzilla.gnome.org/show_bug.cgi?id=675504
docs/reference/gobject/tut_gtype.xml | 143 +++++++++++-----
docs/reference/gobject/tut_howto.xml | 303 +++++++++++++++++++++++-----------
2 files changed, 309 insertions(+), 137 deletions(-)
---
diff --git a/docs/reference/gobject/tut_gtype.xml b/docs/reference/gobject/tut_gtype.xml
index 477a7fe..479537e 100644
--- a/docs/reference/gobject/tut_gtype.xml
+++ b/docs/reference/gobject/tut_gtype.xml
@@ -322,8 +322,9 @@ GType maman_bar_get_type (void)
</para>
<para>
- When having no special requirements you also can use the <function>G_DEFINE_TYPE</function>
- macro:
+ If you have no special requirements you can use the
+ <function><link linkend="G-DEFINE-TYPE:CAPS">G_DEFINE_TYPE</link></function>
+ macro to define a class:
<programlisting>
G_DEFINE_TYPE (MamanBar, maman_bar, G_TYPE_OBJECT)
</programlisting>
@@ -688,7 +689,7 @@ void maman_ibaz_do_action (MamanIbaz *self)
MAMAN_IBAZ_GET_INTERFACE (self)->do_action (self);
}
</programlisting>
- <function>maman_ibaz_get_type</function> registers a type named <emphasis>MamanIBaz</emphasis>
+ <function>maman_ibaz_get_type</function> registers a type named <emphasis>MamanIbaz</emphasis>
which inherits from G_TYPE_INTERFACE. All interfaces must be children of G_TYPE_INTERFACE in the
inheritance tree.
</para>
@@ -706,14 +707,13 @@ void maman_ibaz_do_action (MamanIbaz *self)
Once an interface type is registered, you must register implementations for these
interfaces. The function named <function>maman_baz_get_type</function> registers
a new GType named MamanBaz which inherits from <link linkend="GObject"><type>GObject</type></link> and which
- implements the interface <type>MamanIBaz</type>.
+ implements the interface <type>MamanIbaz</type>.
<programlisting>
static void maman_baz_do_action (MamanIbaz *self)
{
- g_print ("Baz implementation of IBaz interface Action.\n");
+ g_print ("Baz implementation of Ibaz interface Action.\n");
}
-
static void
baz_interface_init (gpointer g_iface,
gpointer iface_data)
@@ -728,7 +728,7 @@ maman_baz_get_type (void)
static GType type = 0;
if (type == 0) {
const GTypeInfo info = {
- sizeof (MamanBazInterface),
+ sizeof (MamanBazClass),
NULL, /* base_init */
NULL, /* base_finalize */
NULL, /* class_init */
@@ -771,22 +771,38 @@ struct _GInterfaceInfo
};
</programlisting>
</para>
+
<para>
- When having no special requirements you also can use the <function>G_DEFINE_INTERFACE</function> macro:
+ If you have no special requirements you can use the
+ <link linkend="G-IMPLEMENT-INTERFACE:CAPS">G_IMPLEMENT_INTERFACE</link> macro
+ to implement an interface:
<programlisting>
-G_DEFINE_INTERFACE (MamanBaz, maman_baz, G_TYPE_OBJECT)
+static void
+maman_baz_do_action (MamanIbaz *self)
+{
+ g_print ("Baz implementation of Ibaz interface Action.\n");
+}
+
+static void
+maman_ibaz_interface_init (MamanIbazInterface *iface)
+{
+ iface->do_action = maman_baz_do_action;
+}
+
+G_DEFINE_TYPE_WITH_CODE (MamanBaz, maman_baz, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (MAMAN_TYPE_IBAZ,
+ maman_ibaz_interface_init));
</programlisting>
</para>
-
<sect2 id="gtype-non-instantiable-classed-init">
<title>Interface Initialization</title>
<para>
- When an instantiable classed type which registered an interface
- implementation is created for the first time, its class structure
- is initialized following the process
- described in <xref linkend="gtype-instantiable-classed"/>.
+ When an instantiable classed type which implements an interface
+ (either directly or by inheriting an implementation from a superclass)
+ is created for the first time, its class structure is initialized
+ following the process described in <xref linkend="gtype-instantiable-classed"/>.
After that, the interface implementations associated with
the type are initialized.
</para>
@@ -802,28 +818,65 @@ G_DEFINE_INTERFACE (MamanBaz, maman_baz, G_TYPE_OBJECT)
</para>
<para>
- Finally, the interface' most-derived <function>base_init</function> function and then
+ The interface's <function>base_init</function> function is called,
+ and then the interface's <function>default_init</function> is invoked.
+ Finally if the type has registered an implementation of the interface,
the implementation's <function>interface_init</function>
- function are invoked. It is important to understand that if there are multiple
- implementations of an interface the <function>base_init</function> and
- <function>interface_init</function> functions will be
- invoked once for each implementation initialized.
+ function is invoked. If there are multiple implementations of an
+ interface the <function>base_init</function> and
+ <function>interface_init</function> functions will be invoked once
+ for each implementation initialized.
</para>
<para>
- It is thus common for base_init functions to hold a local static boolean variable
- which makes sure that the interface type is initialized only once even if there are
- multiple implementations of the interface:
+ It is thus recommended to use a <function>default_init</function> function to
+ initialize an interface. This function is called only once for the interface no
+ matter how many implementations there are. The
+ <function>default_init</function> function is declared by
+ <link linkend="G-DEFINE-INTERFACE:CAPS">G_DEFINE_INTERFACE</link>
+ which can be used to define the interface:
<programlisting>
+G_DEFINE_INTERFACE (MamanIbaz, maman_ibaz, G_TYPE_OBJECT);
+
static void
-maman_ibaz_base_init (gpointer g_iface)
+maman_ibaz_default_init (MamanIbazInterface *iface)
{
- static gboolean initialized = FALSE;
+ /* add properties and signals here, will only called once */
+}
+</programlisting>
+ </para>
- if (!initialized) {
- /* create interface signals here. */
- initialized = TRUE;
+ <para>
+ Or you can do that yourself in a GType function for your interface:
+<programlisting>
+GType
+maman_ibaz_get_type (void)
+{
+ static volatile gsize type_id = 0;
+ if (g_once_init_enter (&type_id)) {
+ const GTypeInfo info = {
+ sizeof (MamanIbazInterface),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ maman_ibaz_default_init, /* class_init */
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ 0, /* instance_size */
+ 0, /* n_preallocs */
+ NULL /* instance_init */
+ };
+ GType type = g_type_register_static (G_TYPE_INTERFACE,
+ "MamanIbaz",
+ &info, 0);
+ g_once_init_leave (&type_id, type);
}
+ return type_id;
+}
+
+static void
+maman_ibaz_default_init (MamanIbazInterface *iface)
+{
+ /* add properties and signals here, will only called once */
}
</programlisting>
</para>
@@ -835,7 +888,6 @@ maman_ibaz_base_init (gpointer g_iface)
</para>
<para>
- The above process can be summarized as follows:
<table id="ginterface-init-table">
<title>Interface Initialization</title>
<tgroup cols="3">
@@ -853,24 +905,31 @@ maman_ibaz_base_init (gpointer g_iface)
</thead>
<tbody>
<row>
- <entry morerows="1">First call to <function><link linkend="g-type-create-instance">g_type_create_instance</link></function> for type
- implementing interface
+ <entry>First call to <function><link linkend="g-type-create-instance">g_type_create_instance</link></function>
+ for <emphasis>any</emphasis> type implementing interface
</entry>
- <entry>interface' base_init function</entry>
- <entry>On interface' vtable</entry>
- <entry>Register interface' signals here (use a local static
- boolean variable as described above to make sure not to register them
- twice.).</entry>
+ <entry>interface's <function>base_init</function> function</entry>
+ <entry>On interface's vtable</entry>
+ <entry>Rarely necessary to use this. Called once per instantiated classed type implementing the interface.</entry>
</row>
<row>
- <!--entry>First call to <function><link linkend="g-type-create-instance">g_type_create_instance</link></function> for type
- implementing interface
- </entry-->
- <entry>interface' interface_init function</entry>
- <entry>On interface' vtable</entry>
+ <entry>First call to <function><link linkend="g-type-create-instance">g_type_create_instance</link></function>
+ for <emphasis>each</emphasis> type implementing interface
+ </entry>
+ <entry>interface's <function>default_init</function> function</entry>
+ <entry>On interface's vtable</entry>
+ <entry>Register interface's signals, properties, etc. here. Will be called once.</entry>
+ </row>
+ <row>
+ <entry>First call to <function><link linkend="g-type-create-instance">g_type_create_instance</link></function>
+ for <emphasis>any</emphasis> type implementing interface
+ </entry>
+ <entry>implementation's <function>interface_init</function> function</entry>
+ <entry>On interface's vtable</entry>
<entry>
- Initialize interface' implementation. That is, initialize the interface
- method pointers in the interface structure to the function's implementation.
+ Initialize interface implementation. Called for each class that that
+ implements the interface. Initialize the interface method pointers
+ in the interface structure to the implementing class's implementation.
</entry>
</row>
</tbody>
diff --git a/docs/reference/gobject/tut_howto.xml b/docs/reference/gobject/tut_howto.xml
index 4401ad6..744552b 100644
--- a/docs/reference/gobject/tut_howto.xml
+++ b/docs/reference/gobject/tut_howto.xml
@@ -794,7 +794,7 @@ b_method_to_call (B *obj, int a)
<title>How to define and implement interfaces</title>
<sect1 id="howto-interface-define">
- <title>How to define interfaces</title>
+ <title>How to define an interface</title>
<para>
The bulk of interface definition has already been shown in <xref linkend="gtype-non-instantiable-classed"/>
@@ -802,7 +802,8 @@ b_method_to_call (B *obj, int a)
</para>
<para>
- As above, the first step is to get the header right:
+ As above, the first step is to get the header right. This interface
+ defines two methods:
<programlisting>
#ifndef __MAMAN_IBAZ_H__
#define __MAMAN_IBAZ_H__
@@ -823,11 +824,13 @@ struct _MamanIbazInterface
GTypeInterface parent_iface;
void (*do_action) (MamanIbaz *self);
+ void (*do_something) (MamanIbaz *self);
};
GType maman_ibaz_get_type (void);
-void maman_ibaz_do_action (MamanIbaz *self);
+void maman_ibaz_do_action (MamanIbaz *self);
+void maman_ibaz_do_something (MamanIbaz *self);
#endif /* __MAMAN_IBAZ_H__ */
</programlisting>
@@ -854,66 +857,51 @@ void maman_ibaz_do_action (MamanIbaz *self);
<para>
The implementation of the <type>MamanIbaz</type> type itself is trivial:
<itemizedlist>
- <listitem><para><function>maman_ibaz_get_type</function> registers the
- type in the type system.
+ <listitem><para><function><link linkend="G-DEFINE-INTERFACE:CAPS">G_DEFINE_INTERFACE</link></function>
+ creates a <function>maman_ibaz_get_type</function> function which registers the
+ type in the type system. The third argument is used to define a
+ <link linkend="howto-interface-prerequisite">prerequisite interface</link>
+ (which we'll talk about more later). Just pass <code>0</code> for this
+ argument when an interface has no prerequisite.
</para></listitem>
- <listitem><para><function>maman_ibaz_base_init</function> is expected
+ <listitem><para><function>maman_ibaz_default_init</function> is expected
to register the interface's signals if there are any (we will see a bit
- (later how to use them). Make sure to use a static local boolean variable
- to make sure not to run the initialization code twice (as described in
- <xref linkend="gtype-non-instantiable-classed-init"/>,
- <function>base_init</function> is run once for each interface implementation
- instantiation)</para></listitem>
- <listitem><para><function>maman_ibaz_do_action</function> dereferences
- the class structure to access its associated class function and calls it.
+ later how to use them).</para></listitem>
+ <listitem><para>The interface methods <function>maman_ibaz_do_action</function>
+ and <function>maman_ibaz_do_something</function> dereference the interface
+ structure to access its associated interface function and call it.
</para></listitem>
</itemizedlist>
<programlisting>
+G_DEFINE_INTERFACE (MamanIbaz, maman_ibaz, 0);
+
static void
-maman_ibaz_base_init (gpointer g_class)
+maman_ibaz_default_init (gpointer g_class)
{
- static gboolean is_initialized = FALSE;
-
- if (!is_initialized)
- {
- /* add properties and signals to the interface here */
-
- is_initialized = TRUE;
- }
+ /* add properties and signals to the interface here */
}
-GType
-maman_ibaz_get_type (void)
+void
+maman_ibaz_do_action (MamanIbaz *self)
{
- static GType iface_type = 0;
- if (iface_type == 0)
- {
- const GTypeInfo info = {
- sizeof (MamanIbazInterface),
- maman_ibaz_base_init, /* base_init */
- NULL, /* base_finalize */
- };
-
- iface_type = g_type_register_static (G_TYPE_INTERFACE, "MamanIbaz",
- &info, 0);
- }
+ g_return_if_fail (MAMAN_IS_IBAZ (self));
- return iface_type;
+ MAMAN_IBAZ_GET_INTERFACE (self)->do_action (self);
}
void
-maman_ibaz_do_action (MamanIbaz *self)
+maman_ibaz_do_something (MamanIbaz *self)
{
g_return_if_fail (MAMAN_IS_IBAZ (self));
- MAMAN_IBAZ_GET_INTERFACE (self)->do_action (self);
+ MAMAN_IBAZ_GET_INTERFACE (self)->do_something (self);
}
</programlisting>
</para>
</sect1>
<sect1 id="howto-interface-implement">
- <title>How To define implement an Interface?</title>
+ <title>How to implement an interface</title>
<para>
Once the interface is defined, implementing it is rather trivial.
@@ -954,15 +942,22 @@ GType maman_baz_get_type (void);
#endif /* __MAMAN_BAZ_H__ */
</programlisting>
+ <!-- Ha ha! "nothing weird or scary". I actually laughed out loud. Oh boy.
+ The fact that we're so intimate with GObject that all this doesn't look
+ wierd, that's the scary thing. :) -->
There is clearly nothing specifically weird or scary about this header:
- it does not define any weird API or derives from a weird type.
+ it does not define any weird API or derive from a weird type.
</para>
<para>
The second step is to implement <type>MamanBaz</type> by defining
- its GType. Instead of using <function>G_DEFINE_TYPE</function> we
- use <function>G_DEFINE_TYPE_WITH_CODE</function> and the
- <function>G_IMPLEMENT_INTERFACE</function> macros.
+ its GType. Instead of using
+ <function><link linkend="G-DEFINE-TYPE:CAPS">G_DEFINE_TYPE</link></function>
+ we use
+ <function><link linkend="G-DEFINE-TYPE-WITH-CODE:CAPS">G_DEFINE_TYPE_WITH_CODE</link></function>
+ and the
+ <function><link linkend="G-IMPLEMENT-INTERFACE:CAPS">G_IMPLEMENT_INTERFACE</link></function>
+ macros.
<programlisting>
static void maman_ibaz_interface_init (MamanIbazInterface *iface);
@@ -971,13 +966,15 @@ G_DEFINE_TYPE_WITH_CODE (MamanBar, maman_bar, G_TYPE_OBJECT,
maman_ibaz_interface_init));
</programlisting>
This definition is very much like all the similar functions we looked
- at previously. The only interface-specific code present here is the call
- to <function>G_IMPLEMENT_INTERFACE</function>.
+ at previously. The only interface-specific code present here is the call to
+ <function><link linkend="G-IMPLEMENT-INTERFACE:CAPS">G_IMPLEMENT_INTERFACE</link></function>.
</para>
- <note><para>Classes can implement multiple interfaces by using multiple
- calls to <function>G_IMPLEMENT_INTERFACE</function> inside the call
- to <function>G_DEFINE_TYPE_WITH_CODE</function>.</para></note>
+ <note><para>Classes can implement multiple interfaces by using multiple calls to
+ <function><link linkend="G-IMPLEMENT-INTERFACE:CAPS">G_IMPLEMENT_INTERFACE</link></function>
+ inside the call to
+ <function><link linkend="G-DEFINE-TYPE-WITH-CODE:CAPS">G_DEFINE_TYPE_WITH_CODE</link></function>
+ </para></note>
<para>
<function>maman_baz_interface_init</function>, the interface
@@ -987,14 +984,22 @@ G_DEFINE_TYPE_WITH_CODE (MamanBar, maman_bar, G_TYPE_OBJECT,
static void
maman_baz_do_action (MamanBaz *self)
{
- g_print ("Baz implementation of IBaz interface Action: 0x%x.\n",
+ g_print ("Baz implementation of Ibaz interface Action: 0x%x.\n",
+ self->instance_member);
+}
+
+static void
+maman_baz_do_something (MamanBaz *self)
+{
+ g_print ("Baz implementation of Ibaz interface Something: 0x%x.\n",
self->instance_member);
}
static void
maman_ibaz_interface_init (MamanIbazInterface *iface)
{
- iface->do_action = baz_do_action;
+ iface->do_action = maman_baz_do_action;
+ iface->do_something = maman_baz_do_something;
}
static void
@@ -1005,17 +1010,16 @@ maman_baz_init (MamanBaz *self)
}
</programlisting>
</para>
-
</sect1>
- <sect1>
+ <sect1 id="howto-interface-prerequisite">
<title>Interface definition prerequisites</title>
<para>
To specify that an interface requires the presence of other interfaces
when implemented, GObject introduces the concept of
<emphasis>prerequisites</emphasis>: it is possible to associate
- a list of prerequisite interfaces to an interface. For example, if
+ 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.
</para>
@@ -1025,16 +1029,15 @@ maman_baz_init (MamanBaz *self)
Java's interface I1 extends interface I2. The example below shows
the GObject equivalent:
<programlisting>
- /* inside the GType function of the MamanIbar interface */
- type = g_type_register_static (G_TYPE_INTERFACE, "MamanIbar", &info, 0);
-
- /* Make the MamanIbar interface require MamanIbaz interface. */
- g_type_interface_add_prerequisite (type, MAMAN_TYPE_IBAZ);
+/* Make the MamanIbar interface require MamanIbaz interface. */
+G_DEFINE_INTERFACE (MamanIbar, maman_ibar, MAMAN_TYPE_IBAZ);
</programlisting>
- The code shown above adds the MamanIbaz interface to the list of
- prerequisites of MamanIbar while the code below shows how an
- implementation can implement both interfaces and register their
- implementations:
+ In the <function><link linkend="G-DEFINE-INTERFACE:CAPS">G_DEFINE_INTERFACE</link></function>
+ 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 the MamanIbar. The code
+ below shows how an implementation can implement both interfaces and
+ register their implementations:
<programlisting>
static void
maman_ibar_do_another_action (MamanIbar *ibar)
@@ -1056,7 +1059,16 @@ maman_ibaz_do_action (MamanIbaz *ibaz)
{
MamanBar *self = MAMAN_BAR (ibaz);
- g_print ("Bar implementation of IBaz interface Action: 0x%x.\n",
+ 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);
}
@@ -1064,6 +1076,7 @@ static void
maman_ibaz_interface_init (MamanIbazInterface *iface)
{
iface->do_action = maman_ibaz_do_action;
+ iface->do_something = maman_ibaz_do_something;
}
static void
@@ -1087,22 +1100,24 @@ G_DEFINE_TYPE_WITH_CODE (MamanBar, maman_bar, G_TYPE_OBJECT,
It is very important to notice that the order in which interface
implementations are added to the main object is not random:
<function><link linkend="g-type-add-interface-static">g_type_add_interface_static</link></function>,
- which is called by <function>G_IMPLEMENT_INTERFACE</function>, must be
- invoked first on the interfaces which have no prerequisites and then on
+ which is called by
+ <function><link linkend="G-DEFINE-INTERFACE:CAPS">G_IMPLEMENT_INTERFACE</link></function>,
+ must be invoked first on the interfaces which have no prerequisites and then on
the others.
</para>
</sect1>
<sect1 id="howto-interface-properties">
- <title>Interface Properties</title>
+ <title>Interface properties</title>
<para>
- Starting from version 2.4 of GLib, GObject interfaces can also have
+ GObject interfaces can also have
properties. Declaration of the interface properties is similar to
declaring the properties of ordinary GObject types as explained in
- <xref linkend="gobject-properties"/>,
- except that <function><link linkend="g-object-interface-install-property">g_object_interface_install_property</link></function> is used to
- declare the properties instead of <function><link linkend="g-object-class-install-property">g_object_class_install_property</link></function>.
+ <xref linkend="gobject-properties"/>, except that
+ <function><link linkend="g-object-interface-install-property">g_object_interface_install_property</link></function>
+ is used to declare the properties instead of
+ <function><link linkend="g-object-class-install-property">g_object_class_install_property</link></function>.
</para>
<para>
@@ -1114,31 +1129,17 @@ G_DEFINE_TYPE_WITH_CODE (MamanBar, maman_bar, G_TYPE_OBJECT,
That really is one line extended to six for the sake of clarity
</para>
</footnote>
- line in the <function>maman_ibaz_base_init</function>
- <footnote>
- <para>
- The <function><link linkend="g-object-interface-install-property">g_object_interface_install_property</link></function>
- can also be called from <function>class_init</function> but it must
- not be called after that point.
- </para>
- </footnote>
- as shown below:
+ line in the <function>maman_ibaz_default_init</function> as shown below:
<programlisting>
static void
-maman_ibaz_base_init (gpointer g_iface)
+maman_ibaz_default_init (gpointer g_iface)
{
- static gboolean is_initialized = FALSE;
-
- if (!is_initialized)
- {
- g_object_interface_install_property (g_iface,
- g_param_spec_string ("name",
- "Name",
- "Name of the MamanIbaz",
- "maman",
- G_PARAM_READWRITE));
- is_initialized = TRUE;
- }
+ g_object_interface_install_property (g_iface,
+ g_param_spec_string ("name",
+ "Name",
+ "Name of the MamanIbaz",
+ "maman",
+ G_PARAM_READWRITE));
}
</programlisting>
</para>
@@ -1152,9 +1153,9 @@ maman_ibaz_base_init (gpointer g_iface)
</para>
<para>
- An implementation shall declare and define it's properties in the usual
+ An implementation declares and defines it's properties in the usual
way as explained in <xref linkend="gobject-properties"/>, except for one
- small change: it must declare the properties of the interface it
+ small change: it can declare the properties of the interface it
implements using <function><link linkend="g-object-class-override-property">g_object_class_override_property</link></function>
instead of <function><link linkend="g-object-class-install-property">g_object_class_install_property</link></function>.
The following code snippet shows the modifications needed in the
@@ -1233,6 +1234,118 @@ maman_baz_class_init (MamanBazClass *klass)
</para>
</sect1>
+
+ <sect1 id="howto-interface-override">
+ <title>Overriding interface methods</title>
+
+ <para>
+ If a base class already implements an interface, and in a derived
+ class you wish to implement the same interface overriding only certain
+ methods of that interface, you just reimplement the interface and
+ set only the interface methods you wish to override.
+ </para>
+
+ <para>
+ In this example MamanDerivedBaz is derived from MamanBaz. Both
+ implement the MamanIbaz interface. MamanDerivedBaz only implements one
+ method of the MamanIbaz interface and uses the base class implementation
+ of the other.
+<programlisting>
+static void
+maman_derived_ibaz_do_action (MamanIbaz *ibaz)
+{
+ MamanDerivedBaz *self = MAMAN_DERIVED_BAZ (ibaz);
+ g_print ("DerivedBaz implementation of Ibaz interface Action\n");
+}
+
+static void
+maman_derived_ibaz_interface_init (MamanIbazInterface *iface)
+{
+ /* Override the implementation of do_action */
+ iface->do_action = maman_derived_ibaz_do_action;
+
+ /*
+ * We simply leave iface->do_something alone, it is already set to the
+ * base class implementation.
+ */
+}
+
+G_DEFINE_TYPE_WITH_CODE (MamanDerivedBaz, maman_derived_baz, MAMAN_TYPE_BAZ,
+ G_IMPLEMENT_INTERFACE (MAMAN_TYPE_IBAZ,
+ maman_derived_ibaz_interface_init)
+
+static void
+maman_derived_baz_class_init (MamanDerivedBazClass *klass)
+{
+
+}
+
+static void
+maman_derived_baz_init (MamanDerivedBaz *self)
+{
+
+}
+</programlisting>
+ </para>
+
+ <para>
+ To access the base class interface implementation use
+ <function><link linkend="g-type-interface-peek-parent">g_type_interface_peek_parent</link></function>
+ from within an interface's <function>default_init</function> function.
+ </para>
+
+ <para>
+ If you wish to call the base class implementation of an interface
+ method from an derived class where than interface method has been
+ overridden then you can stash away the pointer returned from
+ <function><link linkend="g-type-interface-peek-parent">g_type_interface_peek_parent</link></function>
+ in a global variable.
+ </para>
+
+ <para>
+ In this example MamanDerivedBaz overides the
+ <function>do_action</function> interface method. In it's overridden method
+ it calls the base class implementation of the same interface method.
+<programlisting>
+static MamanIbazInterface *maman_ibaz_parent_interface = NULL;
+
+static void
+maman_derived_ibaz_do_action (MamanIbaz *ibaz)
+{
+ MamanDerivedBaz *self = MAMAN_DERIVED_BAZ (ibaz);
+ g_print ("DerivedBaz implementation of Ibaz interface Action\n");
+
+ /* Now we call the base implementation */
+ maman_ibaz_parent_interface->do_action (ibaz);
+}
+
+static void
+maman_derived_ibaz_interface_init (MamanIbazInterface *iface)
+{
+ maman_ibaz_parent_interface = g_type_interface_peek_parent (iface);
+ iface->do_action = maman_derived_ibaz_do_action;
+}
+
+G_DEFINE_TYPE_WITH_CODE (MamanDerivedBaz, maman_derived_baz, MAMAN_TYPE_BAZ,
+ G_IMPLEMENT_INTERFACE (MAMAN_TYPE_IBAZ,
+ maman_derived_ibaz_interface_init)
+
+static void
+maman_derived_baz_class_init (MamanDerivedBazClass *klass)
+{
+
+}
+
+static void
+maman_derived_baz_init (MamanDerivedBaz *self)
+{
+
+}
+</programlisting>
+ </para>
+
+ </sect1>
+
</chapter>
<!-- End Howto Interfaces -->
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]