一. 概述
OC语言支持面向对象那么也就有面向对象编程 (OOP) 语言的一个主要功能就是--继承。那么何为继承呢?我对继承的理解是:继承是指这样一种功能:它可以使用它父类的所有功能包括成员变量和方法,并在无需重新编写原来的类的情况下对这些功能进行扩展。通过继承创建的新类称为“子类”或“派生类”,被继承的类称为“父类”或“超类”。
二 . 继承
继承的好处:
1)不改变原来模型的基础上,拓充方法
2)建立了类与类之间的联系
3)抽取了重复的代码
继承的坏处:
耦合性强,子类严重依赖父类。
继承的细节:
1)单继承:一个类只能有一个父类,不能有多个。
2)子类和父类不能有相同的成员变量。
3)方法的重写:子类重新实现父类中的某个方法,覆盖父类以前父类的方法,具体看下文示例.
4)关于继承关系中方法的调用处理:调用某个对象的方法时优先在子类中找,找不到才去父类中找,在到爷爷类中找。
继承的使用场合:
一个类的所有属性都是你想要的,一般就继承,如果它的部分属性是你想要的,可以从这个类中抽取出另一个父类,但有一点要注意,两个类之间的关系应该是“属于”关系。例如,老师是一个人,学生也是一个人,因此这两个类都可以继承 Person 类。但是 Car类却不能继承 Person类,继承的关系时严格的属于关系,也可以表达成 “子类是父类”如学生是人,但说成汽车是人就不符合逻辑了。
组合关系:
上文说到继承关系应该是子类属于父类,但有一种情况是,一个类拥有另一个类的成员变量,如Score类中包含:数学成绩、语文成绩,但Student类也包含数学成绩和语文成绩,这时不能用Student类继承成绩类因为不能说成学生是成绩,那么这种关系怎么表达呢,那就是组合关系,表达成一个类拥有另一个类,如学生拥有成绩。
简单总结如下:
组合:xxx拥有xxx 例:学生拥有成绩
继承:xx是 xxx 例:学生是人狗是动物
组合关系使用示例:
/* 成绩类的声明 */ @interface Score :NSObject { int mathScore; // 数学成绩 int cScoer; // C语言成继 } /* 成绩类的实现 */ @implementation Score @end /* 学生类的声明 */ @interface Student { // 学生类也要包含两个成绩时,即可使用组合能使用继承 //int mathScore; //int cScoer; Score *_score; int num; } @end /* 学生类的实现 */ @implementation Score @end
三 . 继承使用示例
1 /* Person类的声明 */ 2 @interface Person : NSObject 3 { 4 int _age; // 年龄属性 5 } 6 - (void)setAge:(int)age; 7 - (int)age; 8 // 跑方法 9 - (void)run; 10 @end 11 12 /* Person 类实现 */ 13 @implementation Person 14 - (void)setAge:(int)age 15 { 16 _age = age; 17 } 18 - (int)age 19 { 20 return _age; 21 } 22 23 - (void)run 24 { 25 NSLog(@"Person run!!"); 26 } 27 @end 28 29
下面是学生类从Person类继承并重写了run方法
1 2 3 /* 学生类继承人类 */ 4 // : Person 继承了Person里面所有的成员变量和方法 5 @interface Student : Person 6 { 7 //子类和父类不能有相同的成员变量 8 // int _age; 9 int num; //在父类基础上的扩充学号属性 10 } 11 @end 12 13 @implementation Student 14 /* 重写:子类重新实现父类中的某个方法,覆盖父类以前父类的方法 */ 15 - (void)run 16 { 17 NSLog(@"Student run!!"); 18 } 19 @end</span><span style="font-size:14px;"> 20 </span> 21 22 测试代码: 23 24 25 26 27 28 int main() 29 { 30 /* 31 Dog *d = [Dog new]; 32 [d setAge:5]; 33 NSLog(@"age = %d",[d age]); 34 Cat *c = [Cat new]; 35 [c setAge:3]; 36 NSLog(@"age = %d",[d age]); 37 */ 38 39 Student *s = [Student new]; 40 [s setAge:15]; 41 NSLog(@"age = %d",[s age]); 42 [s run]; 43 //优先在自己的实现中找方法找不到才去父类中找 44 return 0; 45 }
运行结果:
nikodeimac:inherit niko$ ./a.out
2015-03-17 22:22:07.397 a.out[3368:256407] age = 15
2015-03-17 22:22:07.398 a.out[3368:256407] Student run!!
四. self关键字
1.使用 "self->成员变量名"访问当前方法调用的成员变量
2.使用 "[self 方法名];"来调用方法(对象方法类方法)
self 使用注意
1. 引发死循环:
1 @implementation Dog 2 3 - (void)test 4 { 5 //引发死循环 6 [self test] 7 } 8 9 + (void)test1 10 { 11 //引发死循环 12 [self test] 13 } 14 @end
self关键字使用示例1调用对象方法 :
1 /* Dog类的声明 */ 2 @interface Dog : NSObject 3 - (void)bark; // 叫 方法 4 - (void)run; // 跑 方法 5 @end 6 7 @implementation Dog 8 /* 叫方法实现 */ 9 - (void)bark 10 { 11 NSLog(@"汪 汪 汪"); 12 } 13 //跑方法实现 需求:跑之前先叫两次 14 - (void)run 15 { 16 /* self在对象方法中,这个方法只能由对象调用所以self指向当前对象 */ 17 [self bark]; // 调用自己的叫方法两次 18 [self bark]; 19 NSLog(@"跑 跑 跑"); 20 } 21 @end 22 测试代码: 23 int main() 24 { 25 Dog *d = [Dog new]; 26 /* 调用run方法的是对象 */ 27 [d run]; 28 return 0; 29 }
nikodeimac:self niko$ ./a.out
2015-03-17 22:44:20.634 a.out[3402:262954] 汪 汪 汪
2015-03-17 22:44:20.635 a.out[3402:262954] 汪 汪 汪
2015-03-17 22:44:20.635 a.out[3402:262954] 跑 跑 跑