一、概述
通过继承机制,可以利用已有的数据类型来定义新的数据类型。所定义的新的数据类型不仅拥有新定义的成员,而且还同时拥有旧的成员。我们称已存在的用来派生新类的类为基类,又称为父类。由已存在的类派生出的新类称为派生类,又称为子类。
派生类方法属性 = 基类方法属性 + 派生类自己新增的方法和属性
方法重写:从父类继承的方法,当不适合子类使用时,子类可以重写父类方法。
继承的注意事项:
1.子类不能定义和父类相同的变量,但是可以继承父类的变量。
2.父类的私有属性能够被子类继承,但是不能被使用。
3.OC只支持单一继承,不支持多继承,也就是说一个子类只能拥有一个父类。
4.OC支持多层继承。
继承体系中方法的调用顺序:
1.在自己的类中找。
2.如果没有,去父类中找。
3.如果父类中没有,就去父类的父类中找,直到基类(NSObject)。
4.如果最终NSObject也没有,则会报错。
二、继承的代码实现
类 Person 属性:_name 、_age 方法: speak
类Student继承自Person,并且拥有学号_num新属性, 拥有seeMovie新方法。
代码实现:
Person.h
#import <Foundation/Foundation.h>
@interface Person : NSObject
{
int _age;
NSString * _name;
}
@property int age;
@property NSString *name;
-(void) speak;
@end
Person.m
#import "Person.h"
@implementation Person
-(void) speak{
NSLog(@"人在说话");
}
@end
Student.h
#import "Person.h"
@interface Student : Person
{
int _num;
}
@property int num;
-(void) seeMovie;
@end
student.m
#import "Student.h"
@implementation Student
-(void) seeMovie{
NSLog(@"%@正在看电影",_name);
}
@end
main.m
#import <Foundation/Foundation.h>
#import "Student.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Student *s1 = [Student new];
s1.name = @"小明"; //继承自父类的实例变量
s1.age = 12; //继承自父类的实例变量
s1.num = 110; //子类新增的实例变量
[s1 speak]; //输出:人在说话
[s1 seeMovie]; //输出:小明正在看电影
}
return 0;
}
三、方法重写
类Student、Teacher都继承自Person;Student 类的speak方法输出“学生在说话”,Teacher类的speak方法输出“老师在说话”。
代码实现:
Teacher.h
#import "Person.h"
@interface Teacher : Person
@end
Teacher.m
#import "Teacher.h"
@implementation Teacher
-(void) speak{
NSLog(@"老师在说话");
}
@end
Student.m
#import "Student.h"
@implementation Student
-(void) seeMovie{
NSLog(@"%@正在看电影",_name);
}
-(void) speak{
NSLog(@"学生在说话");
}
@end
main.m
#import <Foundation/Foundation.h>
#import "Student.h"
#import "Teacher.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person *p1 = [Person new];
Student *s1 = [Student new];
Teacher *t1 = [Teacher new];
[p1 speak]; // 输出:人在说话
[s1 speak]; // 输出:学生在说话
[t1 speak]; // 输出:老师在说话
}
return 0;
}
四、实例变量修饰符
修饰符:
1.@public
在任意程序中可以使用。可以被子类继承。
2.@protected
同一类和派生类中可以使用。可以被子类继承。
3.@private
同一类中可以使用。可以被子类继承。
注意:子类可以继承父类全部成员变量和方法,所以即使是@private修饰的变量,子类也是可以从父类继承的,只是在子类中无法使用而已。
Person.h
#import <Foundation/Foundation.h>
@interface Person : NSObject
{
@public
NSString *_name;
@protected
int _age;
@private
int _num;
}
@property int age;
@property NSString *name;
@property int num;
-(void) test_public;
-(void) test_protected;
-(void) test_private;
@end
Person.m
#import "Person.h"
@implementation Person
-(void) test_public{
NSLog(@"@Public:%@",_name);
}
-(void) test_protected{
NSLog(@"@Protected:%d",_age);
}
-(void) test_private{
NSLog(@"@Private:%d",_num);
}
@end
Student.h
#import "Person.h"
@interface Student : Person
-(void) test;
@end
Student.m
#import "Student.h"
@implementation Student
-(void) test{
//NSLog(@"姓名:%@,年龄:%d,编号:%d",_name,_age,_num);
//报错信息:Instance Variable '_num'is private
NSLog(@"姓名:%@,年龄:%d",_name,_age);
}
@end
main.m
#import <Foundation/Foundation.h>
#import "Student.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person *p = [Person new];
Student *s = [Student new];
p.name = @"成年人";
p.age = 32;
p.num = 100;
[p test_public];
[p test_protected];
[p test_private];
s.name = @"小明";
s.age = 12;
s.num = 110;
[s test_public];
[s test_protected];
[s test_private];
}
return 0;
}
当子类中使用父类的@private修饰变量时报错: