初识Objective-C语言,很多不明白的地方,类的复合就是其中之一。搞了很久,才知其详义,记录下来,给自己提个醒,也与大家相互交流。如有不当之处,欢迎大家更正。
编程中当我们想描述类与类或对象与对象之间的关系时有两种方法,一个是继承,另一个就是复合。
比如我们想用Teacher类一个的对象,和三个Student类的对象组成一个Classroom对象。Classroom对象中包含了Teacher,Student的属性和方法,但是它们又没有继承的关系,此时就需复合来实现。
Teacher类和Student类都继承于Person类,Person类中定义了一些属性和方法就不在这里实现了.
Teacher.h文件
#import"Person.h"
@classClassroom;
@interface Teachers : Person
{
Classroom *_currentClass;//当前班级
}
- (void)introduce; //自我介绍的方法
@end
注意:在这里我们用@class是为了防止类的循环引入,它只是告诉编译器在Teacher.h我们要用到Classroom类里的属性和方法,并没有真正引进Classroom这个类.那么什么是循环导入呢?看一下下面这张图
A.h想用B.h里的属性和方法,那么在A.h里就得#import"B.h"导入一下B.h,此时B.h已经是A.h的一部分,如果B.h也想用A.h里面的属性和方法.也得去导入A.h,假设可以导入,那么A.h此时也是B.h的一部分.编译器在编译A.h的时候发现它里面有B.h,就去导入B.h,结果发现B.h里也有A.h,就又去导入A.h.因此形成一个循环.导致程序崩溃.
那么本题我们应该怎么办呢?可以用@class 类名告诉编译器在这里有这么一个类,在编译的时候要用到它里面的方法和属性,但并没有真正的把它导入到本类中.
Teacher.m文件
#import"Teachers.h"
#import "Classroom.h"
@implementation Teachers
- (void)introduce
{
NSLog(@"大家好我是老师!");
}
@end
注意:规范考虑,建议大家在.h文件里使用了@class,要在.m文件里使用#import导入相应的类.
student.h文件
#import"Person.h"
@interface Student :Person
- (void)introduce;
@end
student.m文件
@implementation Student
- (void)introduce
{
NSLog(@"我是学生%@ %@ %d",_nickName,_name, _age);
}
@end
Classroom.h文件
#import <Foundation/Foundation.h>
@classTeachers;
@classStudent;
@interface Classroom :NSObject
{
// 复合模式
Teachers *_teachers;
Student *_student1;
Student *_student2;
Student *_student3;
}
// 开班仪式
- (void)ceremony;
- (void)setTeachers:(Teachers *)teacher;
- (void)setStudent1:(Student *)student;
- (void)setStudent2:(Student *)student;
- (void)setStudent3:(Student *)student;
@end
Classroom.m文件
#import "Classroom.h"
#import "Teachers.h"
#import "Student.h"
@implementation Classroom
// 开班仪式
- (void)ceremony
{
[_teachersintroduce];
[_student1introduce];
[_student2introduce];
[_student3introduce];
}
- (void)setTeachers:(Teachers *)teacher
{
_teachers = teacher;
}
- (void)setStudent1:(Student *)student
{
_student1 = student;
}
- (void)setStudent2:(Student *)student
{
_student2 = student;
}
- (void)setStudent3:(Student *)student
{
_student3 = student;
}
@end
注意:使用@class避免了循环导入,但是在main.m需要把用到的类都使用#import导入.
main.m文件
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Classroom.h"
#import "Teachers.h"
#import "Student.h"
int main(int argc,constchar * argv[])
{
Classroom *class16 = [[Classroomalloc]init];
Teachers *a = [[Teachersalloc]initWithNickName:@"**"andName:@"**" andAge:28andMoney:1222];
[class16setTeachers:a];
Student *b = [[Studentalloc]initWithNickName:@"**"andName:@"**" andAge:20andMoney:180];
[class16setStudent1:b];
Student *c = [[Studentalloc]initWithNickName:@"**"andName:@"**" andAge:20 andMoney:255];
[class16setStudent2:c];
Student *d = [[Studentalloc]initWithNickName:@"**"andName:@"**" andAge:28andMoney:1200];
[class16setStudent3:d];
[class16ceremony];
}