Creo que una mejor solución sería hacer el método de una virtual, en lugar de tener B re-implementar la interfaz A está unido a (esto puede requerir más trabajo que acaba de redefinir una función), que se puede hacer así (ejemplo debería ser otra que la completa definición de interfaz fooable):
#include <glib-object.h>
#include "fooable.h"
typedef struct {GObject parent;} A;
typedef struct {
GObjectClass parent;
gint (*foo) (Fooable *self, gdouble quux);
} AClass;
#define TYPE_A (a_get_type())
#define A_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST((cls), TYPE_A, AClass))
#define A_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), TYPE_A, AClass))
gint a_foo_real (Fooable *self, gdouble quux) {
g_print("a_foo_real(%g)\n", quux);
return 5;
}
gint a_foo (Fooable *self, gdouble quux) {
return A_GET_CLASS(self)->foo(self, quux);
}
void implement_fooable (FooableIface *iface) {iface->foo = a_foo;}
void a_class_init (AClass *cls) {cls->foo = a_foo_real;}
void a_init (A *self) {}
G_DEFINE_TYPE_WITH_CODE(A, a, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE(TYPE_FOOABLE, implement_fooable));
/* derive class B from A */
typedef struct {A parent;} B;
typedef struct {AClass parent;} BClass;
#define TYPE_B (b_get_type())
gint b_foo_real (Fooable *self, gdouble quux) {
g_print("b_foo_real(%g)\n", quux);
return 55;
}
void b_class_init (BClass *cls) {A_CLASS(cls)->foo = b_foo_real;}
void b_init (B *self) {}
G_DEFINE_TYPE(B, b, TYPE_A);
int main() {
g_type_init();
A *a = g_object_new(TYPE_A, NULL);
B *b = g_object_new(TYPE_B, NULL);
fooable_foo(FOOABLE(a), 87.0); // a_foo_real(87.0) and returns 5
fooable_foo(FOOABLE(b), 32.0); // b_foo_real(32.0) and returns 55
return 0;
}
que es tan breve de un ejemplo que puedo hacerlo. Cuando llame al fooable_foo()
, la función verá su vtable para la función definida cuando implementó la interfaz que es a_foo()
que mira el vtable de la clase A para determinar a qué función llamar realmente. La definición de clase B anula la clase A de a_foo_real()
con la suya propia. Si necesita el b_foo_real
de la clase B para encadenarse, eso es bastante fácil (use A_CLASS(b_parent_class)->foo()
, que se define para usted en la macro G_DEFINE_TYPE)
Sugiero etiquetar esta pregunta como GObject, porque está más relacionada con ella que GTK +. – ntd
Mirando hacia atrás 2 años después, realmente me siento afortunado de no tener que pelear más con esta mierda. – ablmf
¿Mierda? ESTO ES GOBJEEECT! – ntd