1、接口不是用来搞代码复用以简化对象设计的,而是用来简化对象的上层建筑的设计。
2、接口的使用很简单,只要把一个类继承这个接口,然后实现接口中的方法。
3、接口的模拟大致分为三个部分:
- 接口申明
- 接口定义
- 接口使用
4、接口的申明,以下代码(my-iusb.h)就申明了一个MyIUsb的接口,其实也和封装一个类差不多。
- 实力结构体,空的就行。
- 类结构体,里面第一句要指出父类是GTypeInstance,然后要指出方法的函数指针。
- 接下来要先声明接口函数
- 注意一下接口的命名,My是项目缩写,I是interface的意思,IUSB是接口的名字
#ifndef MY_ISUB_H
#define MY_IUSB_H
/*********接口申明***********/
#include <glib-object.h>
#define MY_TYPE_IUSB (my_iusb_get_type())
#define MY_IUSB(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),MY_TYPE_IUSB,MyIUsb))
//MY_IS_IUSB可以识别某个对象是否属于obj指向的类型
#define MY_IS_IUSB(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),MY_TYPE_IUSB)
//这个宏用于从接口的实例结构体中取出类结构体的指针,具体怎么取得那就是GObject的事
#define MY_IUSB_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE((obj),MY_TYPE_IUSB,MyIUsbInterface))
typedef struct _MyIUsb MyIUsb; //实例结构体 My是项目缩写,USB是接口的名字,I代表interface
typedef struct _MyIUsbInterface MyIUsbInterface;
struct _MyIUsbInterface { //类结构体
GTypeInstance parent_interface;
//这一组函数指针就是接口协议
gchar *(*read)(MyIUsb *self); //read只能返回字符串
void(*write)(MyIUsb *self, const gchar *str);//write只能写入字符串
};
GType my_iusb_get_type(void);
//声明接口,接口便是my_iusb_read, my_iusb_write
gchar *my_iusb_read(MyIUsb *self);
void my_iusb_write(MyIUsb *self, const gchar *str);
#endif // !MY_ISUB_H
5、接口定义,在my-iusb.c里面定义接口。
- g_return_if_fail(MY_IS_IUSB(self)) 在.h文件中定义了这个宏,用来检测对象是否是MY_IS_IUSB类型的
- MY_IUSB_GET_INTERFACE(self) -> read(self) 用来从接口的实力结构体中取出类结构体的指针,具体怎么取的就不管啦
/**********接口的定义***********/
#include "my-iusb.h"
G_DEFINE_INTERFACE(MyIUsb, my_iusb, G_TYPE_INVALID); //与G_TYPE_TYPE类似,为类的实例化提供支持
//是G_DEFINE_INTERFACE宏的展开代码中申明的一个函数,里面可以放一些接口的初始化代码
static void my_iusb_default_init(MyIUsbInterface *iface) {
}
gchar * my_iusb_read(MyIUsb *self) {
g_return_if_fail(MY_IS_IUSB(self));
//MY_IUSB_GET_INTERFACE宏用于从MyIUsb接口的实例结构体中取出类结构体的指针,用这个指针就可以访问接口对应的方法啦
MY_IUSB_GET_INTERFACE(self) -> read(self);
}
void my_iusb_write(MyIUsb *self, const gchar *str) {
g_return_if_fail(MY_IS_IUSB(self)); // MY_IS_IUSB宏用来检测对象是否为MyIUsb类型,在.h文件中定义
MY_IUSB_GET_INTERFACE(self)->write(self, self);
}
6、接口的使用
刚刚说接口的使用就是把一个类继承接口,然后实现这个接口的函数。所以可以在子类的.c文件里这样做:
- 将接口添加到子类中
- 具体定义接口函数
- 表明子类实现了接口的函数
#include "my-udisk.h"
#include "my-iusb.h"
#include <stdio.h>
//以下函数的申明要在G_DEFINE_TYPE_WITH_CODE宏之前,因为这个宏展开代码中要用到这个函数
static void my_iusb_interface_init(MyIUsbInterface *iface);
//这个宏的作用:将接口添加到MyUdisk类中
G_DEFINE_TYPE_WITH_CODE (MyUdisk, my_udisk, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE(MY_TYPE_IUSB, my_iusb_interface_init));
static gchar * my_udisk_read(MyIUsb *iusb) {
MyUdisk *udisk = MY_UDISK(iusb);
return udisk->data->str;
}
static void my_udisk_write(MyIUsb *iusb, const gchar *str) {
MyUdisk *udisk = MY_UDISK(iusb);
g_string_assign(udisk->data, str);
}
static void my_udisk_init(MyUdisk *self) {
self->data = g_string_new(NULL);
}
static void my_udisk_class_init(MyUdiskClass *self) {
}
//表明MyUdisk类实现了MyIUsb所规定的接口
static void my_iusb_interface_init(MyIUsbInterface *iface) {
iface->read = my_udisk_read;
iface->write = my_udisk_write;
}
参考http://garfileo.is-programmer.com/2011/3/15/inheritance-and-interface.25299.html