------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! ———
OC中面向的对象特征之继承和派生
1、OC中的继承与派生
先看下图:
上图是一个抽象描述的特性继承表
交通工具是一个基类(也称做父类),通常情况下所有交通工具所共同具备的特性是速度与额定载人的数量,但按照生活常规,我们来继续给交通工具来细分类的时候,我们会分别想到有汽车类和飞机类等等,汽车类和飞机类同样具备速度和额定载人数量这样的特性,而这些特性是所有交通工具所共有的,那么当建立汽车类和飞机类的时候我们无需再定义基类已经有的数据成员,而只需要描述汽车类和飞机类所特有的特性即可,飞机类和汽车类的特性是由在交通工具类原有特性基础上增加而来的,那么飞机类和汽车类就是交通工具类的派生类(也称作子类)。以此类推,层层递增,这种子类获得父类特性的概念就是继承。
鸟类,有羽毛和飞的方法,麻雀、大雁、鸭子也都羽毛和非的方法
2、继承的代码实现
//
// main.m
// 继承的代码实现
//
#import <Foundation/Foundation.h>
#import "Animal.h"
#import "Dog.h"
#import "BigYellowDog.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Animal *ani = [Animal new];
ani->_age = 1;
[ani eat:@"玉米"];
[ani run];
Dog *d1 = [Dog new];
d1->_age = 3;
[d1 eat:@"一坨新鲜的...!!!"];
[d1 run];
[d1 lookHome];
//BigYellowDog 本身(实际定义)没有吃和跑的行为,
//但是 BigYellowDog 父类 Dog 有
//所以,BigYellowDog 也就有了,因为继承过来的
BigYellowDog *BYD = [BigYellowDog new];
[BYD eat:@"同伴的一坨新鲜的....!!"];
[BYD run];
[BYD catchMouse];
}
return 0;
}
//
// Animal.h
//
#import <Foundation/Foundation.h>
@interface Animal : NSObject
{
//动物的年龄
@public
int _age;
}
-(void)eat:(NSString*)foodName;
-(void)run;
@end
//
// Animal.m
//
#import "Animal.h"
@implementation Animal
-(void)eat:(NSString*)foodName{
NSLog(@"正在吃%@",foodName);
}
-(void)run{
NSLog(@"动物正在跑");
}
@end
//
// Dog.h
//
#import <Foundation/Foundation.h>
#import "Animal.h"
//狗这个类要继承自动物类
//如何继承?
//1)导入要继承的那个类的头文件
//2) @interface Dog :父类名
// Animal
@interface Dog : Animal
-(void)lookHome;
@end
//
// Dog.m
//
#import "Dog.h"
@implementation Dog
-(void)lookHome{
NSLog(@"狗已经进入警戒状态!");
}
@end
//
// Cat.h
//
#import "Animal.h"
@interface Cat : Animal
-(void)catchMouse;
@end
//
// Cat.m
//
#import "Cat.h"
@implementation Cat
-(void)catchMouse{
NSLog(@"猫正在抓老鼠");
}
@end
//
// BigYellowDog.h
//
#import "Dog.h"
@interface BigYellowDog : Dog
-(void)catchMouse;
@end
//
// BigYellowDog.m
//
#import "BigYellowDog.h"
@implementation BigYellowDog
-(void)catchMouse{
NSLog(@"狗拿耗子,多管闲事!");
}
@end
//
// JunDog.h
//
#import "Dog.h"
@interface JunDog : Dog
-(void)zhaDiaoBao;
@end
//
// JunDog.m
//
#import "JunDog.h"
@implementation JunDog
-(void)zhaDiaoBao{
NSLog(@"军犬叼起炸药包迅速的跑了");
}
@end
3、基类和派生类之间的关系
一般情况下,基类和派生类之间的关系如下:
派生类方法属性=基类方法属性+派生类自己新增的方法和属性
注意:
1)基类的私有属性能被继承,不能被使用。
2)OC中的继承是单继承:也就是说一个类只能一个父类,不能继承多个父类
3)继承的合理性:
引用《大话西游》里的一句话来描述继承“人是人他妈生的,妖是妖他妈生的!”
4、方法的重写
方法的重写,从父类继承的方法,可能这个方法并不适合子类,可以在子类中重写父类的方法。
//
// main.m
// 基类和派生类之间的关系
//
#import <Foundation/Foundation.h>
#import "Animal.h"
#import "Dog.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
//先查找当前类有没有eat和 bark,
//如果有,先调用自己的
//如果没有,查看父类有没有bark方法
// 如果父类还没有 去爷爷类
// 如果有,就执行
Dog *d = [Dog new];
[d eat];
[d bark];
//ani 调用它自己的吃和叫得方法
Animal *ani = [Animal new];
[ani eat];
[ani bark];
}
return 0;
}
//
// Dog.h
//
#import "Animal.h"
@interface Dog : Animal
@end
//
// Dog.m
//
#import "Dog.h"
@implementation Dog
//把父类的方法,在子类中重新给实现了
//这种做法就称之为:方法的重写
-(void)eat{
NSLog(@"狗会吃");
}
-(void)bark{
NSLog(@"狗会叫");
}
@end
//
// Animal.h
//
#import <Foundation/Foundation.h>
@interface Animal : NSObject
-(void)eat;
-(void)bark;
@end
//
// Animal.m
//
#import "Animal.h"
@implementation Animal
-(void)eat{
NSLog(@"动物会吃");
}
-(void)bark{
NSLog(@"动物会叫");
}
@end
5、继承的注意事项
1)子类不能定义和父类同名的变量,但是可以继承父类的变量
2)OC类支持单一继承,不支持多继承
3)OC支持多层继承
6、继承体系中方法调用的顺序
1)在自己类中找
2)如果没有,去父类中找
3)如果父类中没有,就去父类的父类中
4)如果父类的父类也没有,就还往上找,直到找到基类(NSObject)
5)如果NSObject都没有就报错了
7、实例变量作用域
最早的写法
(1)@public (公开的)在有对象的前提下,任何地方都可以直接访问。
(2)@protected (受保护的)只能在当前类和子类的对象方法中访问
(3)@private(私有的)只能在当前类的对象方法中才能直接访问
(4)@package(框架级别的)作用域介于私有和公开之间,只要处于同一个框架中就可以直接通过变量名访问
8、变量的修饰符在子类中访问
1)@private私有成员是不能被继承,也不能被外部函数访问。
2)@public公有成员能被继承,也能被外部方法访问
在main中访问
3)@protected保护成员能够被继承,不能够被外部函数访问。
9、实例变量作用域使用注意事项
(1)@interface @end之间声明的成员变量如果不做特别的说明,那么其默认是protected的。
(2)一个类继承了另一个类,那么就拥有了父类的所有成员变量和方法,注意所有的成员变量它都拥有,只是有的它不能直接访问。