面向对象的三大特征为封装,多态和继承。OC作为一门面向对象的语言,自然有类的继承。
OC继承的特点
OC的继承通过父类的语法来实现,实现继承的类被称为子类,被继承的类被称为父类。OC的继承有单继承的特点,每一个子类只能有一个父类,类似于树的结构(一个子结点只能有一个父结点,而一个父结点可以有多个子结点)
OC中子类继承父类的语法如下:
@interface SubClass : SuperClass {
//成员变量定义
}
//方法定义
@end
继承关系的本质是一种“由一般到特殊”的关系,子类继承父类,子类是一种特殊的父类。举个例子,苹果属于一种水果,苹果是水果的子类,是一种特殊的水果。或者说,苹果是水果的扩展,Apple类扩展了Fruit类。
当子类扩展父类时,子类继承的东西:
- 全部成员变量
- 全部方法(包括初始化方法)
#import <Foundation/Foundation.h>
@interface Fruit : NSObject
@property(nonatomic, assign)double weight;
- (void)info;
@end
@implementation Fruit
@synthesize weight;
- (void)info {
NSLog(@"我是一个水果,重%gg。", weight);
}
@end
@interface Apple : Fruit
@end
@implementation Apple
@end
int main() {
@autoreleasepool {
Apple *a = [[Apple alloc] init];
a.weight = 56;
[a info];
}
}
输出:
程序中创建了一个Apple类,继承了Fruit类,当我们创建Apple类的对象后,就可以直接访问本属于Fruit类的weight属性和info方法,这就是继承的作用。
值得注意的是,OC中一个子类A只能有一个直接父类B,如果这个父类还有一个父类C,那么这个父类C就是A的间接父类。OC类只能有一个父类,指的是只能有一个直接父类,而间接父类可以有无穷多个。
重写父类方法
子类扩展了父类,子类是一个特殊的父类。大部分时候,子类总是以父类为基础,额外增加方法。但有的时候,我们需要对某些父类方法进行修改,这时候我们可以重写父类方法。
#import <Foundation/Foundation.h>
@interface Bird : NSObject
- (void)fly;
@end
@implementation Bird
- (void)fly {
NSLog(@"我是鸟,我会飞");
}
@end
@interface Ostrich : Bird
- (void)fly;
@end
@implementation Ostrich
- (void)fly {
NSLog(@"我是鸵鸟,我不会飞");![在这里插入图片描述](https://img-blog.csdnimg.cn/20210525185323333.png)
}
@end
int main() {
@autoreleasepool {
Bird *a = [[Bird alloc] init];
[a fly];
Ostrich *b = [[Ostrich alloc] init];
[b fly];
}
}
输出:
要注意,方法重写的方法签名关键字要完全相同,也就是说方法名和方法签名的形参标签都要完全相同,否则就不算方法重写,而算新增了一种方法。
super关键字
如果在子类方法中调用父类被覆盖的实例方法,可用super关键字调用该方法。
若在上面程序的Ostrich类中增加一个birdfly方法:
- (void)birdfly {
[super fly];
}
新程序为:
#import <Foundation/Foundation.h>
@interface Bird : NSObject
- (void)fly;
@end
@implementation Bird
- (void)fly {
NSLog(@"我是鸟,我会飞");
}
@end
@interface Ostrich : Bird
- (void)fly;
- (void)birdfly;
@end
@implementation Ostrich
- (void)fly {
NSLog(@"我是鸵鸟,我不会飞");
}
- (void)birdfly {
[super fly];
}
@end
int main() {
@autoreleasepool {
Bird *a = [[Bird alloc] init];
[a fly];
Ostrich *b = [[Ostrich alloc] init];
[b fly];
[b birdfly];
}
}
输出:
super是OC提供的一个关键字,用于限定该对象调用从它父类继承得到的属性或方法。与self类似,super也不能出现在类方法中。因为类方法的调用者只能是类本身,而不是对象。
成员变量重名
OC的子类接口部分不允许定义与父类接口部分重名的成员变量,因为子类本就继承父类的成员变量。但类实现部分定义的成员变量被限制在该类内部,因此父类实现部分定义的成员变量不会限制子类定义重名的成员变量。反过来说,子类在实现部分定义的成员变量也不受父类接口部分定义的成员变量影响,若这样定义,父类在接口部分定义的成员变量将会隐藏。因此,子类方法很难直接访问父类的成员变量,此时可以通过调用父类的方法来访问父类中被隐藏的成员变量。
#import <Foundation/Foundation.h>
@interface Parent : NSObject {
int _a;
}
@property(nonatomic, assign)int a;
@end
@implementation Parent
@synthesize a = _a;
- (id)init {
if (self = [super init]) {
self->_a = 5;
}
return self;
}
@end
@interface Sub : Parent
- (void)accessOwner;
@end
@implementation Sub {
int _a;
}
- (id)init {
if(self = [super init]) {
self->_a = 7;
}
return self;
}
- (void)accessOwner {
NSLog(@"子类中_a成员变量:%d", _a);
NSLog(@"父类中被隐藏的_a成员变量:%d", super.a);
}
@end
int main() {
@autoreleasepool {
Sub *sub = [[Sub alloc] init];
[sub accessOwner];
}
}
输出: