聶永的博客

          記錄工作/學習的點點滴滴。

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

          公告

          所有文章皆為原創,若轉載請標明出處,謝謝~

          新浪微博,歡迎關注:

          導航

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

          統計

          常用鏈接

          留言簿(58)

          隨筆分類(130)

          隨筆檔案(151)

          個人收藏

          最新隨筆

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 中方县| 油尖旺区| 龙泉市| 南靖县| 乌兰浩特市| 鄂温| 长子县| 定安县| 海晏县| 米脂县| 通辽市| 株洲市| 邹平县| 铜陵市| 靖江市| 大石桥市| 平谷区| 曲周县| 安塞县| 大渡口区| 郓城县| 汽车| 柘城县| 南投市| 利津县| 左权县| 固始县| 延庆县| 济南市| 石泉县| 清水河县| 喀喇| 陈巴尔虎旗| 手游| 依安县| 山东省| 陆河县| 常德市| 确山县| 翁源县| 昌乐县|