c_socket.io_server筆記之定義私有接口
有些話說
頭文件可以作為接口定義,再加上static修飾符,就很容易定義私有的接口,每一個具體的實現,即所有包含所有私有接口的頭文件,都必須要完整實現所有已聲明但未實現的函數,否則gcc編譯不過去。廢話不多說,進入步驟吧。
開始實施
以毫無用處的blog為例,簡單兩個方法就行了,需要每一個實現暴露一個可以外部調用函數。
定義一個結構,公用
blog.h:
#define _BLOG_H
typedef struct {
char *name;
void (*init)(void);
void (*welcome)(void);
} blog_t;
#endif
這個頭文件定義了一個對象??梢宰杂傻谋话笞杂墒褂胋log_t結構。
定義一個完全私有函數頭文件
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源文件,必須實現welcome與init函數,否則gcc編譯不通過。需要注意此頭文件私有。
編寫實現
blog1.c,僅僅一個實現:
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,默認的實現:
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,添花版:
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 <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

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

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

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 閱讀(1537) 評論(0) 編輯 收藏 所屬分類: socket.io