/**
*C语言模拟go语言对多态的实现
*定义一个接口,一个类实现了该接口的所有函数,
*则这个类即为该接口的实现,不显式声明一个类实现的接口
*
*在C语言中,则定义一个包含一组函数指针的结构体模拟接口
*子类有一个创建该结构体的函数,则表示该子类实现接口
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifndef SAFE_FREE
#define SAFE_FREE(p) \
do \
{ \
free(p); \
p = NULL; \
} while (0)
#endif //SAFE_FREE
/**
*定义接口
*cthis是一个指针,指向实现该接口的类
*eat是接口包含的函数(函数指针)
*/
typedef struct _i_animal
{
void *cthis;
void (*eat)(void *cthis);
} i_animal;
/**
*数据类型rabbit
*含有一个属性name
*/
typedef struct _rabbit
{
char *name;
} rabbit;
/**
*rabbit实现i_animal接口需要的函数
*/
void rabbit_eat(void *cthis)
{
printf("%s eat!\n", ((rabbit*)cthis)->name);
}
/**
*表示rabbit实现了i_animal接口
*该函数返回rabbit对接口i_animal的实现
*/
i_animal *rabbit_i_animal(void *cthis)
{
i_animal *instance = (i_animal*)malloc(sizeof(i_animal));
if (NULL == instance)
{
return NULL;
}
memset(instance, 0, sizeof(i_animal));
instance->cthis = cthis;
instance->eat = rabbit_eat;
return instance;
}
/**
*rabbit的构造函数
*/
rabbit *rabbit_create(void)
{
int nameLength = 10;
rabbit *instance = (rabbit*)malloc(sizeof(rabbit));
if (NULL == instance)
{
return NULL;
}
memset(instance, 0, sizeof(rabbit));
instance->name = (char*)malloc(nameLength*sizeof(char));
if (NULL != instance->name)
{
memset(instance->name, 0, nameLength*sizeof(char));
strcpy(instance->name, "rabbit");
}
return instance;
}
/**
*rabbit的析构函数
*/
void rabbit_release(rabbit *cthis)
{
SAFE_FREE(cthis->name);
SAFE_FREE(cthis);
}
/**
*数据类型cat
*含有一个属性name
*/
typedef struct
{
char *name;
} cat;
/**
*cat实现i_animal接口需要的函数
*/
void cat_eat(void *cthis)
{
printf("%s eat!\n", ((cat*)cthis)->name);
}
/**
*表示cat实现了i_animal接口
*该函数返回cat对接口i_animal的实现
*/
i_animal *cat_i_animal(void *cthis)
{
i_animal *instance = (i_animal*)malloc(sizeof(i_animal));
if (NULL == instance)
{
return NULL;
}
memset(instance, 0, sizeof(i_animal));
instance->cthis = cthis;
instance->eat = cat_eat;
return instance;
}
/**
*cat的构造函数
*/
cat *cat_create(void)
{
int nameLength = 10;
cat *instance = (cat*)malloc(sizeof(cat));
if (NULL == instance)
{
return NULL;
}
memset(instance, 0, sizeof(cat));
instance->name = (char*)malloc(nameLength*sizeof(char));
if (NULL != instance->name)
{
memset(instance->name, 0, nameLength*sizeof(char));
strcpy(instance->name, "cat");
}
return instance;
}
/**
*cat的析构函数
*/
void cat_release(cat *cthis)
{
SAFE_FREE(cthis->name);
SAFE_FREE(cthis);
}
/**
*主函数
*/
int main()
{
// 用于循环遍历的变量
int i = 0;
// 数组的长度
int animals_length = 2;
// 创建rabbit实例
rabbit *rabbit_instance = rabbit_create();
// 创建cat实例
cat *cat_instance = cat_create();
// 保存接口实现的数组
i_animal *animals[2] = {NULL};
// 创建rabbit对接口i_animal的实现
animals[0] = rabbit_i_animal(rabbit_instance);
// 创建cat对接口i_animal的实现
animals[1] = cat_i_animal(cat_instance);
// 模拟多态
for (i = 0; i < animals_length; ++i)
{
// 空指针判断
if (NULL == animals[i])
{
continue;
}
// 同一段代码,不同绑定,结果会不同
animals[i]->eat(animals[i]->cthis);
// 接口由子类对应函数创建,需要手动释放
SAFE_FREE(animals[i]);
}
// 析构rabbit
rabbit_release(rabbit_instance);
// 析构cat
cat_release(cat_instance);
return 0;
}
参考:
1、《我所偏爱的C语言面向对象编程范式》 云风的 BLOG
2、《Go语言初步》 云风的 BLOG
3、《俺使用的C语言面向对象范式》
4、《Go For C++ Programmers(C++程序员指南)》
5、《OO in C(1): C语言中的类模拟和多态,继承》
6、《C语言面向对象的实现---多态性》