面向?qū)ο笳Z言里苫纤,方法是一類對象的通用行為谦屑,我們通常需要定義這些方法方便其它對象調(diào)用甫贯,方法的調(diào)用方式類似下面的方式:
VcamSource source=new VcamSource(....);
MediaType mtype = source.getMediaType();
GObject中,一般使用下面的代碼習慣:
VcamSource *source=g_object_new(VCAM_TYPE_SOURCE, NULL);
MediaType *mtype 牍戚;
vcam_source_getMediaType(source, mtype );
它需要兩部分的實現(xiàn)侮繁, 第一部分在.h文件中的class中定義getMediaType的函數(shù)指針和對外的公用方法:
struct _VcamSourceClass {
GObjectClass parent_class;
//定義
void (*getMediaType) (VcamSource* self, GError** error);
};
void vcam_source_getMediaTyp(VcamSource self, MediaType* typeptr);
~~~
第二部分在.c 文件中實現(xiàn)vcam_source_getMediaTyp虑粥,以及在class的init函數(shù)中給函數(shù)指針一個默認實現(xiàn):
~~~
static void
vcam_source_class_init(VcamSourceClass *kclass) {
/* this is not necessary, except for demonstration purposes.
*
* pure virtual method: mandates implementation in children.
*/
kclass->getMediaType = NULL;
/* merely virtual method. */
kclass->getMediaType = getMediaTyp;
}
static void getMediaTyp(VcamSource* self, MediaType* typeptr)
{
/* Default implementation for the virtual method. */
}
void vcam_source_getMediaTyp(VcamSource *self, MediaType* typeptr)
{
VcamSourceClass* klass;
g_return_if_fail(VCAM_IS_SOURCE(self));
g_return_if_fail(typeptr == NULL || *typeptr == NULL);
klass = VCAM_SOURCE_GET_CLASS(self);
g_return_if_fail(klass->getMediaType != NULL);
klass->getMediaType(self, NULL);
}
~~~
這種對象方法的聲明和調(diào)用方式被稱為**virtual public methods**如孝,它很適合與方法重載的場景,父類聲明虛函數(shù)以及一個默認的實現(xiàn)娩贷,并實現(xiàn)通用的調(diào)用方式**vcam_source_getMediaType**第晰;子類可以根據(jù)自己需求,實現(xiàn)自己的方法彬祖,并在類初始化時提供過父類的函數(shù)指針重新設(shè)置方法調(diào)用茁瘦。這樣調(diào)用方式不變,但是父類和各個子類將有不同的表現(xiàn)行為储笑。
正如它適合類繼承甜熔,GObject做了一個限制:final類是不能用這種方式的,因此我們需要對.h文件進行修改使用G_DECLARE_DERIVABLE_TYPE替換G_DECLARE_FINAL_TYPE:
~~~
#ifndef VCAM_SOURCE_H
#define VCAM_SOURCE_H
#include <glib-object.h>
#define VCAM_TYPE_SOURCE (vcam_source_get_type())
G_DECLARE_DERIVABLE_TYPE(VcamSource, vcam_source, VCAM, SOURCE, GObject)
struct _VcamSource {
GObject parent_instance;
};
struct _VcamSourceClass {
GObjectClass parent_class;
//定義
void (*getMediaType) (VcamSource* self, GError** error);
};
void vcam_source_getMediaTyp(VcamSource *self, MediaType* typeptr);
#endif /* __VCAM_SOURCE_H__ */
那么在final類型的類中聲明方法突倍,就直接用方法聲明(而不是指針)腔稀,并在.c文件中實現(xiàn),鄭重方式就是non-virtual public methods : 在.h文件中直接移除void (getMediaType) (VcamSource self, GError** error);**函數(shù)指針羽历,并且在.c文件中將getMediatype的具體實現(xiàn)直接寫在void vcam_source_getMediaTyp方法中焊虏。
另外GObject還有一種方法的聲明和使用方式,它稱為Virtual private Methods:
在.h文件中只有函數(shù)指針聲明秕磷;同時在.c文件中提供一個默認的實現(xiàn)诵闭,和在class初始化函數(shù)中提供一個默認實現(xiàn)。 這時候這個函數(shù)只用于內(nèi)部的調(diào)用,并且能被子類繼承疏尿。
vcam_source_hasMediaType調(diào)用方式實現(xiàn)瘟芝,vcam_source_hasMediaType_default是提供的默認實現(xiàn)。
#ifndef VCAM_SOURCE_H
#define VCAM_SOURCE_H
#include <glib-object.h>
#define VCAM_TYPE_SOURCE (vcam_source_get_type())
G_DECLARE_DERIVABLE_TYPE(VcamSource, vcam_source, VCAM, SOURCE, GObject)
struct _VcamSource {
GObject parent_instance;
};
struct _VcamSourceClass {
GObjectClass parent_class;
//定義
void (*getMediaType) (VcamSource* self, GError** error);
/*Private helper function to work out whether has a Media Type */
gboolean(*hasMediaType) (VcamSource* self);
};
void vcam_source_getMediaTyp(VcamSource *self, MediaType* typeptr);
#endif /* __VCAM_SOURCE_H__ */
上面的.h文件中聲明一個私有虛擬函數(shù)hasMediaType褥琐,他沒有對應(yīng)的對外的調(diào)用聲明模狭。下面時對應(yīng)的.c文件,這里有調(diào)用方式和默認實現(xiàn)踩衩,并在class初始化中提供這個默認實現(xiàn)嚼鹉。
#include "VcamSource.h"
G_DEFINE_TYPE(VcamSource, vcam_source, G_TYPE_OBJECT)
static void
vcam_source_class_init(VcamSourceClass *kclass) {
/* this is not necessary, except for demonstration purposes.
*
* pure virtual method: mandates implementation in children.
*/
kclass->getMediaType = NULL;
/* merely virtual method. */
kclass->getMediaType = getMediaTyp;
kclass->hasMediaType = vcam_source_hasMediaType_default;
}
static void
vcam_source_init(VcamSource *d) {
}
static void
getMediaTyp(VcamSource* self, MediaType* typeptr)
{
/* Default implementation for the virtual method. */
}
void
vcam_source_getMediaTyp(VcamSource *self, MediaType* typeptr)
{
VcamSourceClass* klass;
g_return_if_fail(VCAM_IS_SOURCE(self));
g_return_if_fail(typeptr == NULL || *typeptr == NULL);
klass = VCAM_SOURCE_GET_CLASS(self);
g_return_if_fail(klass->getMediaType != NULL);
klass->getMediaType(self, NULL);
}
/* this accessor function is static: it is not exported outside of this file. */
static gboolean
vcam_source_hasMediaType(VcamSource* self)
{
return VCAM_SOURCE_GET_CLASS(self)->hasMediaType(self);
}
static gboolean
vcam_source_hasMediaType_default(VcamSource * self)
{
return FALSE;
}
int main(int argc, char** argv) {
GType dtype;
VcamSource* d;
dtype = vcam_source_get_type(); /* or d = T_TYPE_DOUBLE */
if (dtype)
g_print("Registration was a success. The type is %lx.\n", dtype);
else
g_print("Registration failed.\n");
return 0;
}