在面相对象的设计过程中,很重要的一个特性就是实现运行时多态。在我们的前面一篇文章中我们讨论过了如何实现继承。那么这篇文章中我们就将着上一次的例子,来说说在C语言中如何利用语言的灵活性来实现多态。
在继承的例子里,我们实现了一个基类 Person
typedef struct _person{
char name[128];
int age;
void (*setName)(struct _person * person, char* name);
void (*setAge)(struct _person * pseron,int age);
char *(*getName)(struct _person * person,int *len);
int (*getAge)(struct _person * pseron);
}Person;
static void setName(struct _person * person, char* name){
if(person == NULL)
return;
memcpy(person->name, name, strlen(name));
return;
}
static void setAge(struct _person * person,int age){
if(person == NULL)
return;
person->age = age;
return;
}
static char * getName(struct _person * person, int *len){
if(person == NULL)
return NULL;
*len = (int)strlen(person->name);
return person->name;
}
static int getAge(struct _person * person){
if(person == NULL)
return -1;
return person->age;
}
Person * Person_new(char * name, int age){
Person * person = NULL;
person = (Person *)malloc(sizeof(Person));
memset(person, 0, sizeof(Person));
person->getAge = getAge;
person->getName = getName;
person->setName = setName;
person->setAge = setAge;
memcpy(person->name, name, strlen(name));
person->age = age;
return person;
}
void Person_delete(Person * person){
if(person == NULL)
return;
free(person);
return;
}
一个派生类Student
typedef struct _student{
Person *person;
char school[128];
void (*setSchool)(struct _student * student, char *school);
char * (*getSchool)(struct _student * student, int *len);
void (*setName)(struct _student * student, char* name);
void (*setAge)(struct _student * student,int age);
char *(*getName)(struct _student * student,int *len);
int (*getAge)(struct _student * student);
}Student;
static void stu_setSchool(struct _student * student, char *school){
if(student == NULL)
return;
memcpy(student->school, school, strlen(school));
return;
}
static char * stu_getSchool(struct _student * student, int *len){
if(student == NULL)
return NULL;
*len = (int)strlen(student->school);
return student->school;
}
static void stu_setName(struct _student * student, char* name){
if(student == NULL)
return;
student->person->setName(student->person,name);
return;
}
static void stu_setAge(struct _student * student,int age){
if(student == NULL)
return;
student->person->setAge(student->person,age);
return;
}
static char * stu_getName(struct _student * student, int *len){
if(student == NULL)
return NULL;
return student->person->getName(student->person, len);
}
static int stu_getAge(struct _student * student){
if(student == NULL)
return -1;
return student->person->getAge(student->person);
}
Student *Student_new(char * name, int age){
Student * student = NULL;
student = (Student *) malloc(sizeof(Student));
memset(student, 0, sizeof(Student));
student->person = Person_new(name, age);
student->getSchool = stu_getSchool;
student->setSchool = stu_setSchool;
student->getAge =stu_getAge;
student->getName = stu_getName;
student->setName = stu_setName;
student->setAge = stu_setAge;
return student;
}
void Student_delete(Student * student){
if(student == NULL)
return;
Person_delete(student->person);
free((void *)student);
return;
}
这次我们在实现一个Employee
类,并且同样继承自Person
类
typedef struct _employee{
Person *person;
char job[128];
void (*setJob)(struct _employee * employee, char *job);
char * (*getJob)(struct _employee * employee, int *len);
void (*setName)(struct _employee * employee, char* name);
void (*setAge)(struct _employee * employee,int age);
char *(*getName)(struct _employee * employee,int *len);
int (*getAge)(struct _employee * employee);
}Employee;
static void emp_setJob(struct _employee * employee, char *job){
if(employee == NULL)
return;
memcpy(employee->job, job, strlen(job));
return;
}
static char * emp_getJob(struct _employee * employee, int *len){
if(employee == NULL)
return NULL;
*len = (int)strlen(employee->job);
return employee->job;
}
static void emp_setName(struct _employee * employee, char* name){
if(employee == NULL)
return;
employee->person->setName(employee->person,name);
return;
}
static void emp_setAge(struct _employee * employee,int age){
if(employee == NULL)
return;
employee->person->setAge(employee->person,age);
return;
}
static char * emp_getName(struct _employee * employee, int *len){
if(employee == NULL)
return NULL;
return employee->person->getName(employee->person, len);
}
static int emp_getAge(struct _employee * employee){
if(employee == NULL)
return -1;
return employee->person->getAge(employee->person);
}
Employee *Employee_new(char * name, int age){
Employee * employee = NULL;
employee = (Employee *) malloc(sizeof(Employee));
memset(employee, 0, sizeof(Employee));
employee->person = Person_new(name, age);
employee->getJob = emp_getJob;
employee->setJob = emp_setJob;
employee->getAge =emp_getAge;
employee->getName = emp_getName;
employee->setName = emp_setName;
employee->setAge = emp_setAge;
return employee;
}
void Employee_delete(Employee * employee){
if(employee == NULL)
return;
Person_delete(employee->person);
free((void *)employee);
return;
}
然后我们定义一个函数,叫做PrintInfo
用来输出Person
类以及其子类的相关信息。定义如下
void PrintInfo(void * _person){
if(_person != NULL)
{
int len;
Person **person = (Person **)_person;
printf("my information: name %s, age %d\n", (*person)->getName(*person,&len), (*person)->getAge(*person));
return;
}
printf("person is NULL\n");
}
我们的主调用程序如下:
int main(int argc, const char * argv[]) {
int len;
Student *student = Student_new("tom", 15);
printf("Hello, my name is %s, %d years old \n", student->getName(student, &len),student->getAge(student));
Employee * employee = Employee_new("jerry", 28);
printf("Hello, my name is %s, %d years old \n", employee->getName(employee, &len), employee->getAge(employee));
PrintInfo((void *)student);
PrintInfo((void *)employee);
Student_delete(student);
student = NULL;
Employee_delete(employee);
employee = NULL;
return 0;
}
运行之后,我们可以看到输出结果如下:
Hello, my name is tom, 15 years old
Hello, my name is jerry, 28 years old
my information: name tom, age 15
my information: name jerry, age 28
我们这个程序的多态性就体现在的PrintInfo
这个函数里。这样,如果我们设计一个系统,我们也可以做到像用C++ 或用 Java语言一样,针对接口编程。