OC中,继承于NSObject的类统称为 model 类(存字符串)
OC中,只允许单继承,无多继承,协议是间接地实现多继承的方式
继承所有的实例变量和方法,子类可以重写父类的方法
例子:Student继承于Person
Person.h文件
#import <Foundation/Foundation.h>
@interface Person : NSObject
{
NSString *_name;
NSString *_sex; // default is male
NSInteger _age;
}
// 非重写的初始化方法需要进行声明
- (instancetype)initWithSex:(NSString *)sex;
- (instancetype)initWithName:(NSString *)name;
- (instancetype)initWithAge:(NSInteger)age;
- (instancetype)initWithAge:(NSInteger)age sex:(NSString *)sex;
- (instancetype)initWithName:(NSString *)name sex:(NSString *)sex;
- (instancetype)initWithName:(NSString *)name age:(NSInteger)age;
- (instancetype)initWithName:(NSString *)name sex:(NSString *)sex age:(NSInteger)age;
// 便利构造器
+ (instancetype)initWithName:(NSString *)name sex:(NSString *)sex age:(NSInteger)age;
- (void)eat;
- (void)toilet;
@end
Person.m文件
#import "Person.h"
@implementation Person
// 子类如果继承父类,那么在子类的初始化方法中(内部)必须调用父类的初始化方法
// 指定指派初始化方法,可以用来纠错
// 这个初始化方法为指派初始化方法,sex是必须有的
- (instancetype)initWithSex:(NSString *)sex
{
// self, super均为去调用这个实例化方法的对象
self = [super init];
if (self) {
_sex = sex;
}
return self;
}
// 非重写的初始化方法需要进行声明
// 在非指派初始化方法中,自己本身调用指派初始化方法
// 在这些方法中 无sex时,需要赋一个默认值
- (instancetype)init
{
self = [self initWithSex:@"male"];
return self;
}
//- (instancetype)initWithName:(NSString *)name
//{
// self = [self initWithSex:@"male"];
// if (self) {
// _name = name;
// }
//
// return self;
//}
- (instancetype)initWithName:(NSString *)name
{
// 在调用时,也可通过调用自身的init方法来调用指派初始化方法
self = [self init];
if (self) {
_name = name;
}
return self;
}
- (instancetype)initWithAge:(NSInteger)age
{
self = [self init];
if (self) {
_age = age;
}
return self;
}
- (instancetype)initWithAge:(NSInteger)age sex:(NSString *)sex
{
self = [self initWithSex:sex];
if (self) {
_age = age;
}
return self;
}
- (instancetype)initWithName:(NSString *)name sex:(NSString *)sex
{
self = [self initWithSex:sex];
if (self) {
_name = name;
}
return self;
}
- (instancetype)initWithName:(NSString *)name age:(NSInteger)age
{
self = [self init];
if (self) {
_name = name;
_age = age;
}
return self;
}
- (instancetype)initWithName:(NSString *)name sex:(NSString *)sex age:(NSInteger)age
{
self = [self initWithSex:sex];
if (self) {
_name = name;
_age = age;
}
return self;
}
// 便利构造器
+ (instancetype)initWithName:(NSString *)name sex:(NSString *)sex age:(NSInteger)age
{
Person *per = [[Person alloc] initWithName:name sex:sex age:age];
[per eat];
return per;
}
- (void)eat
{
NSLog(@"吃五谷杂粮");
// 哪一个对象去调用一个实例化方法,那么在这个实例化方法中的self就是这个对象本身,不管这个方法是父类的还是子类的(Student调用就是stu,Person调用就是per)
NSLog(@"self = %@", self);
// [self toilet];
}
- (void)toilet
{
// 谁去调用这个实例化方法,这个实例化方法中的self就是谁
NSLog(@"next self = %@", self);
}
@end
Student.h文件
#import <Foundation/Foundation.h>
// 引入Person.h文件
#import "Person.h"
@interface Student : Person// 子类 : 父类
@end
Student.m文件
#import "Student.h"
@implementation Student
- (instancetype)init
{
self = [super init];
return self;
}
// 重写父类方法,不需要再次声明
- (void)eat
{
// 子类对象调用父类方法,super代表子类对象 也要完成父类的东西
[super eat];
NSLog(@"吃果蔬");
NSLog(@"func = %s", __func__);
}
- (void)toilet
{
NSLog(@"上厕所");
NSLog(@"__func__ = %s", __func__);
}
@end
main文件
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Student.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person *per = [[Person alloc] init];
[per eat];
NSLog(@"per = %@\n\n", per);
// Student类继承于Person类
Student *stu = [[Student alloc] init];
[stu eat];
[stu toilet];
NSLog(@"stu = %@\n\n", stu);
// 父类不能强转为子类 去调用子类的方法
Person *pp = [[Person alloc] init];
// [pp toilet];
// [(Student *)pp toilet];
// 子类可以强转为父类
// 如果子类没有重写父类的方法,那么执行父类的方法
// 如果子类重写了父类的方法,那么执行子类重写的方法
Student *ss = [[Student alloc] init];
[(Person *)ss toilet];
}
return 0;
}
打印结果:
吃五谷杂粮
self = <Person: 0x100202850>
per = <Person: 0x100202850>
吃五谷杂粮
self = <Student: 0x100107090>
吃果蔬
__func__ = -[Student eat]
next self = <Student: 0x100107090>
上厕所
__func__ = -[Student toilet]
stu = <Student: 0x100107090>
next self = <Student: 0x10010c320>
上厕所
__func__ = -[Student toilet]