用C語言封裝OC對象(耐心閱讀荞彼,非常重要)

本文的主要內(nèi)容來自這里

前言

做iOS開發(fā)的朋友冈敛,對OC肯定非常了解,那么大家有沒有想過OC中NSInteger,NSObject,NSString這些對象是怎么封裝的鸣皂?接下來我們就使用C語言來一部一部的實(shí)現(xiàn)這個(gè)封裝抓谴。

Object對象

首先我們先封裝一個(gè)Object對象,我們來分析一下:

  • 如果使用C來封裝對象,我們就要用到結(jié)構(gòu)體
  • 每一個(gè)Object都有一個(gè)計(jì)數(shù)器寞缝,這個(gè)計(jì)數(shù)器用來管理對象的釋放
  • 提供一定的方法癌压,能夠retain, release, 獲取計(jì)數(shù)器個(gè)數(shù)

好了,基于上邊的設(shè)計(jì)呢荆陆,我們寫了如下的代碼:

Object.h

#include "Object.h"

// 定義Object對象
typedef struct Object {
    int retainCount;
}Object;

//宏定義方法 方便書寫
#define OBJECTRETAIN(obj) objectRetain((Object*)obj)
#define OBJECTRELEASE(obj) objectRelease((Object*)obj)
#define GETRETAINCOUNT(obj) getRetainCount((Object*)obj)
void objectRetain(Object *obj);
void objectRelease(Object *obj);
int getRetainCount(Object *obj);

接下來滩届,我們只要在.c中實(shí)現(xiàn)這三個(gè)方法就行了。

Object.c

#include "Object.h"
#include <stdlib.h>

void objectRetain(Object *obj) {
    obj -> retainCount += 1;
}

void objectRelease(Object *obj) {
    obj -> retainCount -= 1;
    if (obj -> retainCount <= 0) {
        free(obj);
    }
}

int getRetainCount(Object *obj) {
    return obj -> retainCount;
}

String對象

我們使用C語言的char *來封裝String對象:

String.h

#ifndef String_h
#define String_h

#include <stdio.h>

typedef struct String {
    int retainCount;
    char *value;
}String;

String* newString(char* value);
char* getStringValue(String* ins);


#endif /* String_h */

String.c

#include "String.h"
#include <stdlib.h>
#include "Object.h"

String* newString(char* value) {
    String *str = malloc(sizeof(String));
    objectRetain((Object *)str);
    str -> value = value;
    return str;
}

char* getStringValue(String* ins) {
    return ins -> value;
}

Integer對象

Integer是對Int的封裝被啼。

Integer.h

#ifndef Integer_h
#define Integer_h

#include <stdio.h>

typedef struct Integer{
    int retainCount;
    int value;
    
}Integer;

Integer* newInteger(int value);
int getIntegerValue(Integer* ins);
#endif /* Integer_h */

Integer.c

#include "Integer.h"
#include <stdlib.h>
#include "Object.h"

Integer *newInteger(int value) {
    Integer *new = malloc(sizeof(Integer));
    OBJECTRETAIN(new);
    new->value = value;
    return new;
}

int getIntegerValue(Integer* ins) {
    return ins->value;
}

People對象

People對象中有兩個(gè)屬性帜消,一個(gè)是String類型的姓名,一個(gè)是Integer類型的年齡浓体,原理和上邊的封裝非常相似泡挺。

People.h

#ifndef People_h
#define People_h

#include <stdio.h>
#include "Integer.h"
#include "String.h"

typedef struct People{
    int retainCount;
    String* name;
    Integer* age;
    
}People;

People* newPeople(String *name,Integer *age);
String* getName(People* people);
Integer* getAge(People* people);
#endif /* People_h */

People.c

#include "People.h"
#include <stdlib.h>
#include "Object.h"

People* newPeople(String *name,Integer *age){
    People *newP = malloc(sizeof(People));
    OBJECTRETAIN(newP);
    newP->age = age;
    newP->name = name;
    return newP;
}
String* getName(People* people){
    return people->name;
}
Integer* getAge(People* people){
    return people->age;
}

Array對象

我們上邊定義了好幾個(gè)對象,接下來我們在定義一個(gè)數(shù)組對象命浴,我們最終的目的是娄猫,實(shí)現(xiàn)類似OCNSArray的一些簡單的功能贱除,這這里我們會把People放入數(shù)組中。

  • 數(shù)組需要一個(gè)參數(shù)length,用來獲取數(shù)組中的元素個(gè)數(shù)
  • 還需要一個(gè)參數(shù)capacity,用來說明數(shù)組的容量
  • AnyObject *value,數(shù)組中放著的是一組連續(xù)內(nèi)存的Object對象

代碼分析:

//創(chuàng)建數(shù)組
Array* newArray(){
    Array *arr = malloc(sizeof(Array));
    arr->length = 0;
    arr->capacity = 32;
    arr->value = allocMemoryByCapacity(arr);
    return arr;
}

//分配空間
static AnyObject* allocMemoryByCapacity(Array *arr){
    return malloc(sizeof(People*) * arr->capacity);
}

AnyObject是一個(gè)對象媳溺,他封裝了Object *月幌。malloc函數(shù)分配了一段內(nèi)存后,返回了指向這段內(nèi)存的指針褂删,也就是AnyObject*.

在創(chuàng)建Array的時(shí)候飞醉,value就可以直接使用這個(gè)指針進(jìn)行賦值冲茸,同C中的數(shù)組是一個(gè)概念屯阀。

Array.h

#ifndef Array_h
#define Array_h

#include <stdio.h>
#include "People.h"
#include "Object.h"
typedef Object* AnyObject;

typedef struct Array{
    int length;
    int capacity;
    AnyObject *value;
    
}Array;

Array* newArray();

//增加數(shù)組元素
void addElement(Array *array,AnyObject value);

//刪除
Array* removeIndexAt(Array *arry,int index);

//插入
Array* insertIndexAt(Array *array,AnyObject value,int index);

//查找
AnyObject getValueIndexAt(Array *array,int index);

//獲取數(shù)組長度
int getArrayLength(Array *array);

//銷毀
void destroyArray(Array *array);

//打印
void printArray(Array *arr);

#endif /* Array_h */

Array.c

#include "Array.h"
#include <String.h>
#include <stdlib.h>
#include <assert.h>


//分配空間
static AnyObject* allocMemoryByCapacity(Array *arr){
    return malloc(sizeof(People*) * arr->capacity);
}

//創(chuàng)建數(shù)組
Array* newArray(){
    Array *arr = malloc(sizeof(Array));
    arr->length = 0;
    arr->capacity = 32;
    arr->value = allocMemoryByCapacity(arr);
    return arr;
}

//獲取數(shù)組長度
int getArrayLength(Array *array){
    return array->length;
}

//增加元素
void addElement(Array *array,AnyObject value){
    if (array->length >= array->capacity) {
        array->capacity *= 2;
        AnyObject *oldValue = array->value;
        memcpy(array->value, oldValue, array->length*sizeof(AnyObject));
        free(oldValue);
    }
    OBJECTRETAIN(value);
    array->value[array->length] = value;
    array->length++;
}

//刪除元素
Array* removeIndexAt(Array *arry,int index){
    assert(index >= 0 && index < arry->length);  //斷言 防止越界
    
    OBJECTRELEASE(getValueIndexAt(arry, index));
    
    arry->length -- ;
    for (int i = index; i < arry->length; i++) {
        arry->value[i] = arry->value[i+1];
    }
    return arry;
}

//在指定位置增加元素
Array* insertIndexAt(Array *array,AnyObject value,int index){
    if (array->length >= array->capacity) {
        array->capacity *= 2;
        AnyObject *oldValue = array->value;
        memcpy(array->value, oldValue, array->length*sizeof(AnyObject));
        free(oldValue);
    }
    array->length++;
    
    
    //將元素后移
    for (int i = 1; i <= array->length - index; i++) {
               array->value[array->length - i] = array->value[array->length- i - 1];
        }

      //插入指定位置
    array->value[index] = value;
    OBJECTRETAIN(value);
    return array;
}



//獲取某個(gè)元素
AnyObject getValueIndexAt(Array *array,int index){
    assert(index >= 0 && index < array->length);
    return array->value[index];
}

//銷毀
void destroyArray(Array *array){
    free(array->value);
    free(array);
    printf("數(shù)組被銷毀\n");
}
//打印結(jié)果
void printArray(Array *arr){
    for (int i = 0; i < arr->length; i++) {
        printf("位置:%d,姓名:%s,年齡:%d\n",i, getStringValue(getName((People*)getValueIndexAt(arr, i))),getIntegerValue(getAge((People*)getValueIndexAt(arr, i))));
    }
}

測試

在這里下載源碼https://github.com/agelessman/MCC-2-OC-Object.git

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市轴术,隨后出現(xiàn)的幾起案子难衰,更是在濱河造成了極大的恐慌,老刑警劉巖逗栽,帶你破解...
    沈念sama閱讀 211,348評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件盖袭,死亡現(xiàn)場離奇詭異,居然都是意外死亡彼宠,警方通過查閱死者的電腦和手機(jī)鳄虱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,122評論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來凭峡,“玉大人拙已,你說我怎么就攤上這事〈菁剑” “怎么了倍踪?”我有些...
    開封第一講書人閱讀 156,936評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長索昂。 經(jīng)常有香客問我建车,道長,這世上最難降的妖魔是什么椒惨? 我笑而不...
    開封第一講書人閱讀 56,427評論 1 283
  • 正文 為了忘掉前任缤至,我火速辦了婚禮,結(jié)果婚禮上康谆,老公的妹妹穿的比我還像新娘领斥。我一直安慰自己,他們只是感情好秉宿,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,467評論 6 385
  • 文/花漫 我一把揭開白布戒突。 她就那樣靜靜地躺著,像睡著了一般描睦。 火紅的嫁衣襯著肌膚如雪膊存。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,785評論 1 290
  • 那天,我揣著相機(jī)與錄音隔崎,去河邊找鬼今艺。 笑死,一個(gè)胖子當(dāng)著我的面吹牛爵卒,可吹牛的內(nèi)容都是我干的虚缎。 我是一名探鬼主播,決...
    沈念sama閱讀 38,931評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼钓株,長吁一口氣:“原來是場噩夢啊……” “哼实牡!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起轴合,我...
    開封第一講書人閱讀 37,696評論 0 266
  • 序言:老撾萬榮一對情侶失蹤创坞,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,141評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡徘溢,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,483評論 2 327
  • 正文 我和宋清朗相戀三年往堡,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,625評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出席函,到底是詐尸還是另有隱情,我是刑警寧澤澜建,帶...
    沈念sama閱讀 34,291評論 4 329
  • 正文 年R本政府宣布向挖,位于F島的核電站,受9級特大地震影響炕舵,放射性物質(zhì)發(fā)生泄漏何之。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,892評論 3 312
  • 文/蒙蒙 一咽筋、第九天 我趴在偏房一處隱蔽的房頂上張望溶推。 院中可真熱鬧,春花似錦奸攻、人聲如沸蒜危。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽辐赞。三九已至,卻和暖如春硝训,著一層夾襖步出監(jiān)牢的瞬間响委,已是汗流浹背新思。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留赘风,地道東北人夹囚。 一個(gè)月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像邀窃,于是被迫代替她去往敵國和親荸哟。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,492評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 國家電網(wǎng)公司企業(yè)標(biāo)準(zhǔn)(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報(bào)批稿:20170802 前言: 排版 ...
    庭說閱讀 10,926評論 6 13
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法瞬捕,類相關(guān)的語法鞍历,內(nèi)部類的語法,繼承相關(guān)的語法山析,異常的語法堰燎,線程的語...
    子非魚_t_閱讀 31,598評論 18 399
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理掏父,服務(wù)發(fā)現(xiàn)笋轨,斷路器,智...
    卡卡羅2017閱讀 134,629評論 18 139
  • 一、基本數(shù)據(jù)類型 注釋 單行注釋:// 區(qū)域注釋:/* */ 文檔注釋:/** */ 數(shù)值 對于byte類型而言...
    龍貓小爺閱讀 4,257評論 0 16
  • 《一清池》 青墨泅水琉璃瓦 映年華往事 款款日月從容過 我愿執(zhí)筆輕試竹紙塵埃 依依再題 如若華發(fā)斑斑替青絲柳煙 繞...
    紫薔薇簡書閱讀 1,604評論 31 33