+
+typedef struct HerbivoreClass
+{
+ InterfaceClass parent;
+
+ void (*feed_greens)(Herbivore *obj);
+} HerbivoreClass;
+
+static void herbivore_feed_greens(Herbivore *herbie)
+{
+ HerbivoreClass *k = HERBIVORE_GET_CLASS(herbie);
+
+ k->feed_greens(herbie);
+}
+
+static TypeInfo herbivore_info = {
+ .name = TYPE_HERBIVORE,
+ .parent = TYPE_INTERFACE,
+ .class_size = sizeof(HerbivoreClass),
+};
+
+#define TYPE_CARNIVORE "carnivore"
+#define CARNIVORE_CLASS(klass) \
+ OBJECT_CLASS_CHECK(CarnivoreClass, (klass), TYPE_CARNIVORE)
+#define CARNIVORE_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(CarnivoreClass, (obj), TYPE_CARNIVORE)
+#define CARNIVORE(obj) \
+ INTERFACE_CHECK(Carnivore, (obj), TYPE_CARNIVORE)
+
+typedef struct Carnivore
+{
+ Object parent;
+} Carnivore;
+
+typedef struct CarnivoreClass
+{
+ InterfaceClass parent;
+
+ void (*feed_bugs)(Carnivore *obj);
+} CarnivoreClass;
+
+static void carnivore_feed_bugs(Carnivore *carnie)
+{
+ CarnivoreClass *k = CARNIVORE_GET_CLASS(carnie);
+
+ k->feed_bugs(carnie);
+}
+
+static TypeInfo carnivore_info = {
+ .name = TYPE_CARNIVORE,
+ .parent = TYPE_INTERFACE,
+ .class_size = sizeof(CarnivoreClass),
+};
+
+#define TYPE_REPTILE "reptile"
+#define REPTILE(obj) OBJECT_CHECK(Reptile, (obj), TYPE_REPTILE)
+
+typedef struct Reptile
+{
+ Object parent;
+} Reptile;
+
+static TypeInfo reptile_info = {
+ .name = TYPE_REPTILE,
+ .instance_size = sizeof(Reptile),
+ .abstract = true,
+ .class_size = sizeof(ObjectClass),
+};
+
+#define TYPE_LIZARD "lizard"
+#define LIZARD(obj) OBJECT_CHECK(Lizard, (obj), TYPE_LIZARD)
+
+typedef struct Lizard
+{
+ Reptile parent;
+} Lizard;
+
+static TypeInfo lizard_info = {
+ .name = TYPE_LIZARD,
+ .parent = TYPE_REPTILE,
+ .instance_size = sizeof(Lizard),
+ .abstract = true,
+};
+
+#define TYPE_IGUANA "iguana"
+#define IGUANA(obj) OBJECT_CHECK(Iguana, (obj), TYPE_IGUANA)
+
+typedef struct Iguana
+{
+ Lizard parent;
+ int greens;
+} Iguana;
+
+static void iguana_feed(Herbivore *herbie)
+{
+ Iguana *iggie = IGUANA(herbie);
+
+ iggie->greens++;
+}
+
+static void iguana_class_initfn(ObjectClass *klass, void *data)
+{
+ HerbivoreClass *iface = HERBIVORE_CLASS(klass);
+
+ iface->feed_greens = iguana_feed;
+}
+
+static TypeInfo iguana_info = {
+ .name = TYPE_IGUANA,
+ .parent = TYPE_LIZARD,
+ .instance_size = sizeof(Iguana),
+ .class_init = iguana_class_initfn,
+ .interfaces = (InterfaceInfo[]) {
+ { TYPE_HERBIVORE },
+ { }
+ },
+};
+
+#define TYPE_BEARDED_DRAGON "bearded-dragon"
+#define BEARDED_DRAGON(obj) OBJECT_CHECK(BeardedDragon, (obj),
TYPE_BEARDED_DRAGON)
+
+typedef struct BeardedDragon
+{
+ Lizard parent;
+ int bugs;
+} BeardedDragon;
+
+static void bearded_dragon_feed(Carnivore *carnie)
+{
+ BeardedDragon *dragon = BEARDED_DRAGON(carnie);
+
+ dragon->bugs++;
+}
+
+static void bearded_dragon_class_initfn(ObjectClass *klass, void *data)
+{
+ CarnivoreClass *iface = CARNIVORE_CLASS(klass);
+
+ iface->feed_bugs = bearded_dragon_feed;
+}
+
+static TypeInfo bearded_dragon_info = {
+ .name = TYPE_BEARDED_DRAGON,
+ .parent = TYPE_LIZARD,
+ .instance_size = sizeof(BeardedDragon),
+ .class_init = bearded_dragon_class_initfn,
+ .interfaces = (InterfaceInfo[]) {
+ { TYPE_CARNIVORE },
+ { }
+ },
+};
+
+static void basic_init(void)
+{
+ BeardedDragon dragon;
+ Iguana iguana;
+
+ object_initialize(&dragon, TYPE_BEARDED_DRAGON);
+
+ g_assert_cmpint(dragon.bugs, ==, 0);
+ carnivore_feed_bugs(CARNIVORE(&dragon));
+ g_assert_cmpint(dragon.bugs, ==, 1);
+
+ object_finalize(&dragon);
+
+ object_initialize(&iguana, TYPE_IGUANA);
+
+ g_assert_cmpint(iguana.greens, ==, 0);
+ herbivore_feed_greens(HERBIVORE(&iguana));
+ g_assert_cmpint(iguana.greens, ==, 1);
+
+ object_finalize(&iguana);
+}
+
+int main(int argc, char **argv)
+{
+ g_test_init(&argc,&argv, NULL);
+
+ module_call_init(MODULE_INIT_QOM);
+
+ type_register_static(&carnivore_info);
+ type_register_static(&herbivore_info);
+
+ type_register_static(&reptile_info);
+ type_register_static(&lizard_info);
+ type_register_static(&iguana_info);
+ type_register_static(&bearded_dragon_info);
+
+ g_test_add_func("/basic/init", basic_init);
+
+ g_test_run();
+
+ return 0;
+}
--
1.7.5.4