一、多态性
面向对象的基本思考方式是将数据和处理数据的行为放到一起,降低耦合性。其要点就是不要将数据和处理数据的行为分开
在 http://blog.csdn.net/kangguang/article/details/79229064中“带有检查功能的栈”的示例代码就将上限数据,下限数据和栈自身的数据都放在了栈结构体中,结果增加了耦合性。也就是说,仅将数据整合在一起,是绝对无法降低耦合性的。
面向对象编程有许多特性,其中非常重要的一个特性就是多态性。所谓多态性就是指从调用者的角度看对象,会发现它们非常相似,难以区分,但是这些被调用对象的内部处理实际上各不相同。在上篇的例子中,在校验push函数的值时,调用者只会调用Validator的 Validator函数,从外部并不知道其中到底进行了怎样的校验处理。
bool validate(Validator * p,int val)
{
if (!p)
{
return true;
}
return p->validator(p,val);
}
实际上内部到底进行了怎样的校验处理,取决于Validator自身。像这样,通过将数据和处理成对分离,并使用结构体和函数指针实现多态性,被分离出来的部分也可以作为组件被重复利用。
二、继承
typedef struct Validator{
bool (* const validator)( struct Validator * pThis,int val);//1
void * const pData;//2
}Validator;
这个方法适用于简单情况,但情况稍微复杂一些,就显得麻烦了。范围检查校验器中,这个pData指向的是Range结构体。假设现在需要扩展检查校验器的功能,使得栈中只能接受奇数或者偶数,那么仅简单地扩展Range的话,程序中的角色就会变得很模糊。虽然C不是面向对象语言,无法使用继承功能优雅地解决这个问题,但还是有稍好一点的办法的。
重新对代码进行编写:
//1
typedef struct Validator{
bool (* const validator)( struct Validator * pThis,int val);
}Validator;
//2
typedef struct{
//2-1
Validator base;
const int min;
const int max;
}RangeValidator;
//3
typedef struct{
Validator base;//3-1
int previousValue;
}PreviousValueValidator;
#define newRangeValidator(min,max){ \
{validateRange}, \
(min),(max) \
}
#define newPreviousValidator(){ \
{validatePrevious}, \
0 \
}
bool validateRange(Validator * pThis,int val)
{
RangeValidator * pRange = (RangeValidator *)pThis;
return pRange->min<=val && val<= pRange->max;
}
bool validatePrevious(Validator * pThis,int val)
{
PreviousValueValidator * pPrevious =(PreviousValueValidator *)pThis;
if (val<pPrevious->previousValue)
{
return false;
}
pPrevious->previousValue = val;
return true;
}
int buf[16];
RangeValidator validator = newRangeValidator(0, 9);
Stack stack = newStackWithValidator(buf, &validator.base);
按照以下方法将RangeValidator 作为base使用即可扩展 RangeValidator
typedef struct
{
RangeValidator base;
//true 表示需要进行奇偶校验
const bool needOddEventCheck;
//false 表示必须是奇数
const bool needToBeOdd;
}OddEventRangeValidator;
这样,C中就可以使用继承了!