- 浏览: 129830 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
cloverprince:
z707208280 写道写多表查询咋整? select 列 ...
[自己动手]用Java的反射实现DAO -
z707208280:
写多表查询咋整? select 列 这里用别名.字段 这咋整手 ...
[自己动手]用Java的反射实现DAO -
亮亮婷婷:
4楼正解,顶!
能在Eclipse 3.7中给m2e提供WTP支持的插件在哪里? -
cloverprince:
沙舟狼客 写道貌似2b青年的代码很有技术含量嗯,简单问题复杂化 ...
普通青年 文艺青年 2B青年 -
沙舟狼客:
貌似2b青年的代码很有技术含量
普通青年 文艺青年 2B青年
In this article I will implement a class inheriting another.
An inherited class is also known as a "child class", a "derived class" or a "subclass". The class it inherits is call the "parent class", the "base class" or the "superclass". The subclass contains all the data its superclass has and all the methods, properties and signals its superclass has and hence plays whatever part its parent plays according to the Liskov Substitution Principle
Full code here. A bit big. Skip it.
There are two classes and the second inherites the first.
In this program I define two classes separately. The base class is define as before.
Note the my_fundamental_info struct:
I added the G_TYPE_FLAG_DERIVABLE flag to allow this class to be inherited.
I also added G_TYPE_FLAG_DEEP_DERIVABLE so that the subclass can also be inherited. Not all derivable types in GObject are deeply derivable. "Interface" is one exception. Unlike in Java and C#, an Interface cannot inherit another Interface in GObject, but it may have "prerequisites" which require other Interfaces to be also implemented. This will be discussed in later articles.
Note the implementation of function get_base_type(). Here are some tricks:
And note the class struct.
There is a member a_virtual_instance_method, which is a function pointer. This is a virtual method of this class. It is ready to be overridden by the subclass.
The derived class (subclass):
Note how this class is registered. It is no longer a fundamental class because it is a subclass of another.
So the GTypeFundamentalInfo is no longer needed. I don't need to provide the numerical type-id, either. I just tell GObject the base type, the class name and provide the GTypeInfo struct.
And see the structs
The first members are always the corresponding struct of the base class.
Q: How does the derived class override the virtual method of the base class?
A: By modifying the function pointer in the class structure in THE DERIVED CLASS.
In the class init function of the derived class, I cast the klass pointer to its parent type and then modify the a_virtual_instance_method in it.
In GObject, before a class is initialized, the class struct of its base class IS COPIED BYTE BY BYTE into the first portion of the class struct of this class. Therefore the derived class automatically inherites all virtual methods from its parent. Since the class structs of the parent and child are allocated separately, changing the class struct of the child does not modify its parent.
In the main function, I create an instance of the derived class.
In order to access the members inherited from the base class, I cast the type using G_TYPE_CHECK_INSTANCE_CAST and it will do some runtime type checking. Then I can access its parent's member from there.
The most exciting part is the polymorphism which allows the base class and the derived class act differently through the virtual method.
Since the type information is saved in the beginning of each instance, GObject can retrieve their respective class struct using the unified G_TYPE_INSTANCE_GET_CLASS macro. Both of the the returned pointers have type mybaseclass_t, but they point to different class structs which contains different virtual method pointers. That's why the "class structs" in GObject behave like "virtual method tables" in C++ and many other language implementations.
An inherited class is also known as a "child class", a "derived class" or a "subclass". The class it inherits is call the "parent class", the "base class" or the "superclass". The subclass contains all the data its superclass has and all the methods, properties and signals its superclass has and hence plays whatever part its parent plays according to the Liskov Substitution Principle
Full code here. A bit big. Skip it.
/* A fundamental type. Instantiatable and inheritable. */ #include <stdio.h> #include <glib-object.h> /*** base class ***/ // Instance structure typedef struct { GTypeInstance something_as_boilerplate; int a_base_instance_member; } mybaseinstance_t; // Class structure typedef struct { GTypeClass something_as_boilerplate; void (*a_virtual_instance_method)(mybaseinstance_t *instance); } mybaseclass_t; // A virtual method (to be installed) void my_base_method(mybaseinstance_t *instance) { printf("This is base.\n"); } // Class init function void class_init_func_of_base(mybaseclass_t *klass, gpointer data) { klass->a_virtual_instance_method = my_base_method; } // Instance init function void instance_init_func_of_base(mybaseinstance_t *instance, gpointer data) { instance->a_base_instance_member = 42; } // Type registerer. GType get_base_type() { static GType my_type_id=0; if(my_type_id==0) { static const GTypeInfo my_type_info = { sizeof(mybaseclass_t), //class_size; NULL, //base_init; NULL, //base_finalize; /* classed types, instantiated types */ (GClassInitFunc)class_init_func_of_base, //class_init; NULL, //class_finalize; NULL, //class_data; /* instantiated types */ sizeof(mybaseinstance_t),//instance_size; 0, //n_preallocs; (GInstanceInitFunc)instance_init_func_of_base, //instance_init; /* value handling */ NULL, //value_table; }; static const GTypeFundamentalInfo my_fundamental_info = { G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE }; my_type_id = g_type_register_fundamental( g_type_fundamental_next(), "MyBaseClass", &my_type_info, &my_fundamental_info, 0 ); } return my_type_id; } /*** derived class ***/ // Instance structure typedef struct { mybaseinstance_t parent; int a_derived_instance_member; } myderivedinstance_t; // Class structure typedef struct { mybaseclass_t parent_klass; } myderivedclass_t; GType get_derived_type(); // A prototype // A virtual method (will override base virtual method) void my_derived_method(mybaseinstance_t* instance) { myderivedinstance_t *derived = G_TYPE_CHECK_INSTANCE_CAST( instance, get_derived_type(), myderivedinstance_t); printf("This is derived.\n"); } // Class init function void class_init_func_of_derived(myderivedclass_t *klass, gpointer data) { mybaseclass_t *klass_as_base = G_TYPE_CHECK_CLASS_CAST(klass,get_base_type(),mybaseclass_t); klass_as_base->a_virtual_instance_method = my_derived_method; } // Instance init function void instance_init_func_of_derived(myderivedinstance_t *instance, gpointer data) { instance->a_derived_instance_member = 65; } // Type registerer. GType get_derived_type() { static GType my_type_id=0; if(my_type_id==0) { static const GTypeInfo my_type_info = { sizeof(myderivedclass_t), //class_size; NULL, //base_init; NULL, //base_finalize; /* classed types, instantiated types */ (GClassInitFunc)class_init_func_of_derived, //class_init; NULL, //class_finalize; NULL, //class_data; /* instantiated types */ sizeof(myderivedinstance_t),//instance_size; 0, //n_preallocs; (GInstanceInitFunc)instance_init_func_of_derived, //instance_init; /* value handling */ NULL, //value_table; }; my_type_id = g_type_register_static( get_base_type(), "MyDerivedClass", &my_type_info, 0 ); } return my_type_id; } int main() { g_type_init(); printf("Base: %d %s\n",get_base_type(), g_type_name(get_base_type())); printf("Derived: %d %s\n",get_derived_type(), g_type_name(get_derived_type())); /* Test the base class */ mybaseinstance_t *binstance = (mybaseinstance_t*)g_type_create_instance(get_base_type()); printf("base instance member: %d\n",binstance->a_base_instance_member); /* Test the derived class */ myderivedinstance_t *dinstance = (myderivedinstance_t*)g_type_create_instance(get_derived_type()); printf("derived instance member: %d\n",dinstance->a_derived_instance_member); mybaseinstance_t *derived_as_base = G_TYPE_CHECK_INSTANCE_CAST(dinstance, get_base_type(), mybaseinstance_t); printf("base member in derived: %d\n", derived_as_base->a_base_instance_member); /* Test polymorphism */ mybaseinstance_t *instances[2] = { binstance, derived_as_base }; int i; for(i=0;i<2;i++) { mybaseinstance_t *inst = instances[i]; mybaseclass_t *klass = G_TYPE_INSTANCE_GET_CLASS(inst, get_base_type(), mybaseclass_t); klass->a_virtual_instance_method(inst); } return 0; }
There are two classes and the second inherites the first.
In this program I define two classes separately. The base class is define as before.
/*** base class ***/ // Instance structure typedef struct { GTypeInstance something_as_boilerplate; int a_base_instance_member; } mybaseinstance_t; // Class structure typedef struct { GTypeClass something_as_boilerplate; void (*a_virtual_instance_method)(mybaseinstance_t *instance); } mybaseclass_t; // A virtual method (to be installed) void my_base_method(mybaseinstance_t *instance) { printf("This is base.\n"); } // Class init function void class_init_func_of_base(mybaseclass_t *klass, gpointer data) { klass->a_virtual_instance_method = my_base_method; } // Instance init function void instance_init_func_of_base(mybaseinstance_t *instance, gpointer data) { instance->a_base_instance_member = 42; } // Type registerer. GType get_base_type() { static GType my_type_id=0; if(my_type_id==0) { static const GTypeInfo my_type_info = { sizeof(mybaseclass_t), //class_size; NULL, //base_init; NULL, //base_finalize; /* classed types, instantiated types */ (GClassInitFunc)class_init_func_of_base, //class_init; NULL, //class_finalize; NULL, //class_data; /* instantiated types */ sizeof(mybaseinstance_t),//instance_size; 0, //n_preallocs; (GInstanceInitFunc)instance_init_func_of_base, //instance_init; /* value handling */ NULL, //value_table; }; static const GTypeFundamentalInfo my_fundamental_info = { G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE }; my_type_id = g_type_register_fundamental( g_type_fundamental_next(), "MyBaseClass", &my_type_info, &my_fundamental_info, 0 ); } return my_type_id; }
Note the my_fundamental_info struct:
static const GTypeFundamentalInfo my_fundamental_info = { G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE };
I added the G_TYPE_FLAG_DERIVABLE flag to allow this class to be inherited.
I also added G_TYPE_FLAG_DEEP_DERIVABLE so that the subclass can also be inherited. Not all derivable types in GObject are deeply derivable. "Interface" is one exception. Unlike in Java and C#, an Interface cannot inherit another Interface in GObject, but it may have "prerequisites" which require other Interfaces to be also implemented. This will be discussed in later articles.
Note the implementation of function get_base_type(). Here are some tricks:
- On the first call, the type is registered and assigned to my_type_id.
- my_type_id keeps its value between calls since it is static.
- On subsequent calls to this function, the type id will be returned directly without registering the class again.
- See Singleton Pattern for the above design pattern.
And note the class struct.
// Class structure typedef struct { GTypeClass something_as_boilerplate; void (*a_virtual_instance_method)(mybaseinstance_t *instance); } mybaseclass_t;
There is a member a_virtual_instance_method, which is a function pointer. This is a virtual method of this class. It is ready to be overridden by the subclass.
The derived class (subclass):
/*** derived class ***/ // Instance structure typedef struct { mybaseinstance_t parent; int a_derived_instance_member; } myderivedinstance_t; // Class structure typedef struct { mybaseclass_t parent_klass; } myderivedclass_t; GType get_derived_type(); // A prototype // A virtual method (will override base virtual method) void my_derived_method(mybaseinstance_t* instance) { myderivedinstance_t *derived = G_TYPE_CHECK_INSTANCE_CAST( instance, get_derived_type(), myderivedinstance_t); printf("This is derived.\n"); } // Class init function void class_init_func_of_derived(myderivedclass_t *klass, gpointer data) { mybaseclass_t *klass_as_base = G_TYPE_CHECK_CLASS_CAST(klass,get_base_type(),mybaseclass_t); klass_as_base->a_virtual_instance_method = my_derived_method; } // Instance init function void instance_init_func_of_derived(myderivedinstance_t *instance, gpointer data) { instance->a_derived_instance_member = 65; } // Type registerer. GType get_derived_type() { static GType my_type_id=0; if(my_type_id==0) { static const GTypeInfo my_type_info = { sizeof(myderivedclass_t), //class_size; NULL, //base_init; NULL, //base_finalize; /* classed types, instantiated types */ (GClassInitFunc)class_init_func_of_derived, //class_init; NULL, //class_finalize; NULL, //class_data; /* instantiated types */ sizeof(myderivedinstance_t),//instance_size; 0, //n_preallocs; (GInstanceInitFunc)instance_init_func_of_derived, //instance_init; /* value handling */ NULL, //value_table; }; my_type_id = g_type_register_static( get_base_type(), "MyDerivedClass", &my_type_info, 0 ); } return my_type_id; }
Note how this class is registered. It is no longer a fundamental class because it is a subclass of another.
my_type_id = g_type_register_static( get_base_type(), "MyDerivedClass", &my_type_info, 0 ); }
So the GTypeFundamentalInfo is no longer needed. I don't need to provide the numerical type-id, either. I just tell GObject the base type, the class name and provide the GTypeInfo struct.
And see the structs
// Instance structure typedef struct { mybaseinstance_t parent; int a_derived_instance_member; } myderivedinstance_t; // Class structure typedef struct { mybaseclass_t parent_klass; } myderivedclass_t;
The first members are always the corresponding struct of the base class.
Q: How does the derived class override the virtual method of the base class?
A: By modifying the function pointer in the class structure in THE DERIVED CLASS.
// Class init function void class_init_func_of_derived(myderivedclass_t *klass, gpointer data) { mybaseclass_t *klass_as_base = G_TYPE_CHECK_CLASS_CAST(klass,get_base_type(),mybaseclass_t); klass_as_base->a_virtual_instance_method = my_derived_method; }
In the class init function of the derived class, I cast the klass pointer to its parent type and then modify the a_virtual_instance_method in it.
In GObject, before a class is initialized, the class struct of its base class IS COPIED BYTE BY BYTE into the first portion of the class struct of this class. Therefore the derived class automatically inherites all virtual methods from its parent. Since the class structs of the parent and child are allocated separately, changing the class struct of the child does not modify its parent.
In the main function, I create an instance of the derived class.
/* Test the derived class */ myderivedinstance_t *dinstance = (myderivedinstance_t*)g_type_create_instance(get_derived_type()); printf("derived instance member: %d\n",dinstance->a_derived_instance_member); mybaseinstance_t *derived_as_base = G_TYPE_CHECK_INSTANCE_CAST(dinstance, get_base_type(), mybaseinstance_t); printf("base member in derived: %d\n", derived_as_base->a_base_instance_member);
In order to access the members inherited from the base class, I cast the type using G_TYPE_CHECK_INSTANCE_CAST and it will do some runtime type checking. Then I can access its parent's member from there.
The most exciting part is the polymorphism which allows the base class and the derived class act differently through the virtual method.
/* Test polymorphism */ mybaseinstance_t *instances[2] = { binstance, derived_as_base }; int i; for(i=0;i<2;i++) { mybaseinstance_t *inst = instances[i]; mybaseclass_t *klass = G_TYPE_INSTANCE_GET_CLASS(inst, get_base_type(), mybaseclass_t); klass->a_virtual_instance_method(inst); }
Since the type information is saved in the beginning of each instance, GObject can retrieve their respective class struct using the unified G_TYPE_INSTANCE_GET_CLASS macro. Both of the the returned pointers have type mybaseclass_t, but they point to different class structs which contains different virtual method pointers. That's why the "class structs" in GObject behave like "virtual method tables" in C++ and many other language implementations.
发表评论
-
GObject 2-01: A convention-compliant minimal complete working example.
2009-12-18 01:19 2135My coding style has been so wei ... -
GObject 09: An Interface
2009-11-09 16:56 1916An interface is a class with mu ... -
GObject 08: A class with a signal
2009-10-22 17:09 2615A GObject may emit signals to s ... -
GObject 07: A class with properties.
2009-10-22 16:17 1957A good practice of Object-orien ... -
GObject 06: A subclass of GObject
2009-10-21 13:44 1729This time GObject refers to the ... -
GObject 04: A class with private members
2009-10-21 00:49 1912A private member is a member th ... -
GObject 03: An Instantiatable Class
2009-10-16 16:35 1823Most of the time classes are in ... -
GObject 02: A classed type
2009-10-13 16:53 1803Now I am going to create a clas ... -
GObject 01: My first fundamental type.
2009-10-13 01:25 1868GObject system handles "ty ... -
GObject 00: A bottom-up introduction to the GObject system
2009-10-13 00:34 2169This document introduces the GO ...
相关推荐
- NEW: Support for setting GObject.data in editor. - NEW: Support for setting selectedIcon of list item in editor. - IMPROVED: Add UIConfig.depthSupportForPaitingMode. - IMPROVED: Set sorting order of...
离线安装包,亲测可用
Vala 是一种面向对象的、类型安全的、高性能的语言,设计用于生成原生的C代码,并且与GNOME的GObject系统紧密集成。它提供了一种简洁的语法,类似于C#,使得开发GNOME应用更加高效和方便。 根据压缩包子文件的文件...
离线安装包,亲测可用
离线安装包,亲测可用
3. **资源文件**:如GObject Introspection数据,这些用于生成跨语言绑定,使得其他语言(如Python、Vala)可以调用gnome-font-viewer的API。 4. **Makefile**:指导编译过程的文件,定义了如何将源代码编译成可执行...
Groonga GObject 描述 Groonga的GObject包装器。 去做... 安装 Debian GNU / Linux 。 运行以下命令: % sudo apt-get install -V -y gir1.2-groonga libgroonga-gobject0 的Ubuntu 。 运行以下命令: % ...
gir_ffi, 在运行时使用 FFI,为基于GObject的库自动生成绑定 GirFFI由 Matijs van Zuijlen描述使用GObject内省存储库的GNOME的ruby 绑定。状态 特性为基于任何gobject的库创建绑定。在运行时生成绑定。为选定方法...
离线安装包,亲测可用
Doombox 一种音乐播放器,设计时考虑了大型音乐收藏。 文献资料 2.xx 1.xx ... Error: GLib-GObject:ERROR:../../../gobject/gbinding.c:574:g_binding_constructed: assertion failed: (binding->
dpkg -i python-gobject-2_2.28.6-14ubuntu1_amd64.deb wget http://security.ubuntu.com/ubuntu/pool/universe/p/pycairo/python-cairo_1.16.2-2ubuntu2_amd64.deb dpkg -i python-cairo_1.16.2-2ubuntu2_amd64....
官方离线安装包,亲测可用
使用方法类似Qt的信号槽,优点是不需要moc;基于c++11,用于解耦合;GOSP(GUI框架)以此信号槽为特色和基础; signal/slot which is Qt-Style, and not depends on moc
本示例用于演示GObject创建新类,类的继承与重载。代码实现了shape和square类,继承关系为: square -> shape ->gobject 其中,square重载了shape类的info接口。
在实际开发中,开发者通常会利用 GObject 机制来扩展 Libsoup 功能,创建自定义的请求处理器或响应处理器。GObject 是 GNOME 平台上的面向对象编程基础设施,支持继承、接口和信号等特性,使得代码更易于组织和复用...
在IT领域,特别是软件开发中,GObject是一个关键的概念,它是GTK+库中的基础对象模型。GObject系统为C语言提供了面向对象编程的支持,而这个"gobject_setup_property_demo.zip"压缩包显然提供了一个关于如何使用...
离线安装包,亲测可用
离线安装包,亲测可用