Re: howto write an interface
- From: Tommi Komulainen <tommi komulainen iki fi>
- To: David Nečas <yeti physics muni cz>
- Cc: gtk-list gnome org, joel krähemann <joel weedlight ch>
- Subject: Re: howto write an interface
- Date: Mon, 13 Sep 2010 15:05:08 +0100
On Tue, Sep 7, 2010 at 8:32 AM, David Nečas <yeti physics muni cz> wrote:
> On Mon, Sep 06, 2010 at 09:05:37PM +0200, joel krähemann wrote:
>> Hi, I want to write an interface with glib-object. The situation is a
>> parent object implements the interface, but the subclass should
>> overwrite the function pointers in the interface. The parent class
>> contains the following code in the function ags_recall_get_type:
>>
>> ...
>>
>> static const GInterfaceInfo ags_connectable_interface_info = {
>> (GInterfaceInitFunc) ags_recall_connectable_interface_init,
>> NULL, /* interface_finalize */
>> NULL, /* interface_data */
>> };
>>
>> ...
>>
>> g_type_add_interface_static(ags_type_recall,
>> AGS_TYPE_CONNECTABLE,
>> &ags_connectable_interface_info);
>>
>> ...
>>
>> AgsRecall has subclasses which should overwrite the functions, but I
>> don't know what's the proper way in the subclass to do so. How do I tell
>> GInterface to call a function of the subclass to overwrite?
>> One more, is it correct to make an object cast on the interface e.g.
>> (where AgsConnectable is an interface which is implemented by
>> AgsRecall):
>>
>> void
>> ags_recall_connect(AgsConnectable connectable)
>> {
>> AGS_RECALL(connectable);
>>
>> ...
>> }
>
> This sounds somehow backwards.
>
> 1) You define an interface, with a virtual table, i.e. struct
> AgsConnectableInterface, containing the method connect():
>
> struct _AgsConnectableInterface {
> GTypeInterface parent;
>
> void (*connect)(AgsConnectable *connectable);
> };
>
>
> 2) Then standard macros AGS_TYPE_CONNECTABLE, AGS_CONNECTABLE,
> AGS_IS_CONNECTABLE, AGS_CONNECTABLE_GET_INTERFACE, see the docs.
>
> 3) Methods of this interface, e.g. ags_connectable_connect(), get
> AgsConnectable* as the argument and look up the virtual method to call:
>
> void
> ags_connectable_connect(AgsConnectable *connectable)
> {
> void (*connect_method)(AgsConnectable*);
>
> g_return_if_fail(AGS_IS_CONNECTABLE(connectable));
> connect_method = AGS_CONNECTABLE_GET_INTERFACE(connectable)->connect;
> g_return_if_fail(connect_method);
> connect_method(connectable);
> }
>
> There is no public ags_recall_connect() as this makes no sense. To
> invoke the connect() method of AgsRecall (or any other class
> implementing the interface) you call
>
> ags_connectable_connect(AGS_CONNECTABLE(recall));
>
> 4) Each class implementing the interface, including subclasses of
> something that already implements the interface, does
>
> {
> static const GInterfaceInfo ags_connectable_interface_info = {
> (GInterfaceInitFunc)ags_recall_connectable_init, NULL, NULL
> };
> g_type_add_interface_static(g_define_type_id,
> AGS_TYPE_CONNECTABLE,
> &ags_connectable_interface_info);
> }
>
> in the type init function ags_recall_type_init().
I think one point to mention is that you'll need to implement all the
interface methods in subclasses again, even if you just want to use
the implementation in the parent.
> 5) Function ags_recall_connectable_init() gets the virtual table
> AgsConnectableInterface as the argument and fills it:
>
> static void
> ags_recall_connectable_init(AgsConnectableInterface *iface)
> {
> iface->connect = ags_recall_connect;
> }
>
> where ags_recall_connect() is a static function implementing the method,
> not public.
Maybe also add (untested)
7) in order to call the parent implementation of the interface methods
from derived class, say AgsTotalRecall that is subclass of AgsRecall,
use g_type_interface_peek_parent()
static void
ags_total_recall_connect(AgsConnectable *connectable)
{
AgsTotalRecall *self = AGS_TOTAL_RECALL(connectable);
AgsConnectable *parent;
g_debug("Hello world!"); // or whatever
parent = g_type_interface_peek_parent(connectable);
ags_connectable_connect(parent);
}
I suppose an alternative would be for ags_connectable_connect() to
recursively call peek_parent and call the first non-NULL method. Would
slightly reduce boilerplate in derived classes.
--
Tommi Komulainen tommi komulainen iki fi
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]