[glib] Fix up GObject interface documentation



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 (&amp;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",
+                                        &amp;info, 0);
+    g_once_init_leave (&amp;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",
-                                           &amp;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", &amp;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]