聂永的博客

记录工作/学习的点点滴滴。

c_socket.io_server笔记之定义私有接口

有些话说

头文件可以作为接口定义,再加上static修饰符,就很容易定义私有的接口,每一个具体的实现,即所有包含所有私有接口的头文件,都必须要完整实现所有已声明但未实现的函数,否则gcc编译不过去。废话不多说,进入步骤吧。

开始实施

以毫无用处的blog为例,简单两个方法就行了,需要每一个实现暴露一个可以外部调用函数。

定义一个结构,公用

blog.h:

    #ifndef _BLOG_H
    
#define _BLOG_H
    
    typedef 
struct {
        
char *name;
        
void (*init)(void);
        
void (*welcome)(void);
    } blog_t;
    
    
#endif

这个头文件定义了一个对象。可以自由的被包含,包含之后自由使用blog_t结构。

定义一个完全私有函数头文件

blog_impl.h:

#ifndef _BLOG_IMPL_H
#define _BLOG_IMPL_H

#include 
<stdlib.h>
#include 
<stdio.h>
#include 
<string.h>

#include 
"blog.h" //继承blog.h文件

static void welcome(void);
static void init(void);

static blog_t *gen_default(char *name) {
    blog_t 
*blog = (blog_t *)malloc(sizeof(blog_t));
    blog
->name = strdup(name);
    blog
->init = init;
    blog
->welcome = welcome;

    
return blog;
}

#endif

这个文件声明定义了若干static属性的函数,因此,只要包含此头文件的C源文件,必须实现welcomeinit函数,否则gcc编译不通过。需要注意此头文件私有。

编写实现

blog1.c,仅仅一个实现:

#include "blog_impl.h"

static blog_t *this;

static void init(void){
    printf(
"the blog owner is %s\n"this->name);
}

static void welcome(void){
    printf(
"here is the %s haha !\n"this->name);
}

blog_t 
*gen_blog1_ptr(){
    blog_t 
*blog = gen_default("blog1");
    
this = blog;

    
return blog;
}

仅有一个对外入口:gen_blog1_ptr,也就是此实现对外唯一的交互方式。

blog2.c,默认的实现:

#include "blog_impl.h"

static void init(void){
    printf(
"Here is the default blog init action !\n");
}

static void welcome(void){
    printf(
"The system's welcome action !\n");
}

blog_t 
*gen_blog2_ptr(){
    blog_t 
*blog = gen_default("default");

    
return blog;
}

此文件对外唯一入口为:gen_blog2_ptr

其实两个实现已经可以了,但多一个说明接口单一,实现多样性,再说锦上添花也是人们喜欢做的事情。 blog3.c,添花版:

#include "blog_impl.h"

static blog_t *this;

static void init(void){
    printf(
"Hi, %s\n"this->name);
}

static void welcome(void){
    printf(
"you are welcome %s!\n"this->name);
}

blog_t 
*gen_blog3_ptr(){
    blog_t 
*blog = gen_default("blog3");
    
this = blog;

    
return blog;
}

一样可以看到类似约定好的对外函数名称gen_blog3_ptr

应用端实现

我们以app.c作为应用入口:

#include <stdio.h>
#include 
<stdlib.h>

#include 
"blog.h"

int main(int argc, char const *argv[]) {
    blog_t 
*blog1 = gen_blog1_ptr();
    blog_t 
*blog2 = gen_blog2_ptr();
    blog_t 
*blog3 = gen_blog3_ptr();

    printf(
"the blog1's actions \n");
    blog1
->init();
    blog1
->welcome();
    printf(
"\n");

    printf(
"the blog2's actions \n");
    blog2
->init();
    blog2
->welcome();
    printf(
"\n");

    printf(
"the blog3's actions \n");
    blog3
->init();
    blog3
->welcome();
    printf(
"\n");

    
return 0;
}

这里分别调用blog1.c, blog2.c, blog3.c,唯一入口,执行简单的逻辑。

编译运行

编译命令行代码很简单:

gcc -o app app.c blog1.c blog2.c blog3.c

运行:

./app

运行效果:

the blog1's actions ...
the blog owner is blog1
here is the blog1 haha !

the blog2's actions ... Here is the default blog init action !
The system's welcome action !

the blog3's actions ...
Hi, blog3
you are welcome blog3!

小结

这里借助两个头文件,模拟了私有接口,公有结构体对象,三个具体子类实现。
c_socket.io_server项目中,作用于具体的实现,以及定义了传输通道模型和实现,互相不干扰。
当然和JAVA相比,模拟对象程度稍低了一些,但够用了。这个世界不仅仅只有面向对象,还有面向并发的函数式Erlang,还有面向软件工程的大型语言Go。嗯,面向对象不过是这个世界其中一角,天生存在缺陷,也不是被所有人喜欢。组件公用、库的概念,倒是大部分语言都很自然的欣然接受。面向过程,面向对象,不过是大部分人给与的标签,怎么用才重要。

posted on 2013-03-29 17:18 nieyong 阅读(1520) 评论(0)  编辑  收藏 所属分类: socket.io


只有注册用户登录后才能发表评论。


网站导航:
 

公告

所有文章皆为原创,若转载请标明出处,谢谢~

新浪微博,欢迎关注:

导航

<2013年3月>
242526272812
3456789
10111213141516
17181920212223
24252627282930
31123456

统计

常用链接

留言簿(58)

随笔分类(130)

随笔档案(151)

个人收藏

最新随笔

搜索

最新评论

阅读排行榜

评论排行榜