前言
为了了解面对对象的特性,没有比用c语言这样一门语言从零开始实现一次更彻底。首先很感激生命中出现了一位臧老师这样的导师带着我们折腾。
面向对象特性
用过面向对象语言的人都知道,面向对象的一些基本组成成分
例如:
- 类
- 实例
- 状态(属性集)
性质有下:- 独特性
- 私密性
- 可变性
- 行为(方法集)
性质有下:- 同一类具备同一行为
- 查询自己的状态
- 改变自己的状态
- 触发其他实例的行为
- 关系
- 类的关系
- 实例的关系
- 行为的关系
归纳起来就3个重要的特性: 封装性,继承性,多态性
封装性的性质:
- 行为与状态结合形成一个整体
- 隐藏细节
- 公开接口
继承性:
- 拓展现有封装
- 区别“基于对象”和“面向对象”
多态性:
- 相同行为子类多种实现
- 通过父类抽象访问行为
- 不同子类给以不同响应
初步实现
结构体表示类
- 结构体定义->结构体变量
- 类->实例
- 抽象->实体
1 | typedef struct ClassA { |
除了用结构体字段来表示状态还可以用kv存储,连续地址偏移量的方式,另外用结构体存状态不能在运行时自省个,也不利于隐藏细节
函数聚合表示行为
方法有3个要素,执行者,方法名,参数,不同的面向对象语言有自己存放方法的方法,c++语言就是散列存放的,javascript是存放在实例当中,oc、ruby存放在类当中
散列存放方式
- 实现简单
- 理解简单
- 无法实现封装
- 无法重载
1
2
3
4
5
6
7
8
9
10
11void police_arrest(Police_Officer *police, User *somebody);
void police_call_partner(Police_Officer *police, Police_Officer *another);
int police_level(Police_Officer *police);
void CGContextBeginPath(CGContextRef cg_nullable c);
void CGContextMoveToPoint(CGContextRef cg_nullable c,
CGFloat x, CGFloat y);
void CGContextAddRects(CGContextRef cg_nullable c,
const CGRect * __nullable rects, size_t count);
CGPoint CGContextConvertPointToUserSpace(CGContextRef cg_nullable c,
CGPoint point);
存放于实例的方式
- 实例容易替换方法
- 理解简单
- 查询方法简单
- 父类方法不易找到
- 对象占用过多内存
1 | typedef void Arrest_Type(struct Police_Man *self, |
存放于类
- 内存更节约
- 便于实现继承链
- 对象和类的模型更复杂
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17typedef void Arrest_Type(struct Police_Man *self,
struct Thief *thief);
typedef void Call_Partner_Type(struct Police_Man *self,
struct Police_Man *partner);
typedef struct Police_Man_MTable {
Arrest_Type *arrest;
Call_Partner_Type *call_partner;
} Police_Man_MTable;
typedef struct Police_Man {
Police_Man_MTable *mtable;
int police_id;
} Police_Man;
Police_Man_MTable global_police_man_mtable;
采用方案
- 属性:结构体表示字段
- 类和实例:结构体定义、结构体变量
- 方法存放:存放在类上
实现封装性
1 | typedef void Arrest_Type(struct Police_Man *self, |
1 | police_man->mtable->arrest(police_man, thief); |
1 | void arrest_imp(struct Police_Man *self, |
隐藏细节1
2
3
4typedef struct Thief {
struct Thief_MTable *mtable;
float money;
} Thief;1
2
3
4
5
6
7
8
9typedef struct Thief_Private_Data {
int tools_count;
} Thief_Private_Data;
typedef struct Thief_Private {
struct Thief_MTable *mtable;
float money;
Thief_Private_Data *private;
} Thief_Private;
1 | typedef void Dealloc_Type(struct Thief *self); |
1 | void thief_dealloc(struct Thief_Private *self) { |
1 | Thief *new_thief() { |
实现继承性
car是父类,扩写一个子类taxi1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24struct Car;
typedef void Car_Dealloc_Type(struct Car *self);
typedef void Drive_Type(struct Car *self, int meter);
typedef int DriveTimes_Type(struct Car *self);
typedef const char *Color_Type(struct Car *self);
typedef struct Car_MTable {
Car_Dealloc_Type *dealloc;
Drive_Type *drive;
DriveTimes_Type *drive_times;
Color_Type *color;
} Car_MTable;
Car_MTable global_car_mtable;
typedef struct Car {
Car_MTable *mtable;
int total_meters;
void *private;
} Car;
属性扩写1
2
3
4
5
6
7
8
9
10
11
12
13
14typedef struct Car {
Car_MTable *mtable;
int total_meters;
void *private;
} Car;
typedef struct Taxi {
Car super;
float change;
void *private;
} Taxi;
Taxi *taxi = (Taxi *)malloc(sizeof(Taxi));
Car *car = (Car *)taxi;
方法扩写1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18typedef struct Car_MTable {
Car_Dealloc_Type *dealloc;
Drive_Type *drive;
DriveTimes_Type *drive_times;
Color_Type *color;
} Car_MTable;
Car_MTable global_car_mtable;
typedef struct Taxi_MTable {
Car_MTable super;
Taxi_Init_Type *init;
Available_Type *available;
Pick_Up_Type *pick_up;
Set_Off_Type *set_off;
} Taxi_MTable;
Taxi_MTable global_taxi_mtable;
实现多态性
1 | void taxi_drive(Taxi *self, int meters) { |
1 | Taxi *new_taxi() { |
1 | void test3() { |