前面的笔记中定义的BNRPerson类,继承了NSObject类。因此,BNRPerson实例不仅拥有BNRPerson中定义的实例变量和方法,还拥有NSObject中定义的实例变量和方法。
打开BMITime项目,创建一个BNREmployee类。
#import <Foundation/Foundation.h>
//导入BNRPerson.h
#import "BNRPerson.h"
//改为继承BNRPerson
@interface BNREmployee : BNRPerson
//添加三个属性,员工ID,办公室警急码和入职时间
@property (nonatomic) unsigned int employeeID;
@property (nonatomic) unsigned int officeAlarmCode;
@property (nonatomic) NSDate *hireDate;
//添加一个方法,获取入职年限
- (double) yearsOfEmployment;
@end
在BNREmployee.m中实现方法
#import "BNREmployee.h"
@implementation BNREmployee
- (double) yearsOfEmployment
{
//首先判断hireDate是否为nil
if(self.hireDate){
NSDate *now = [NSDate date];
NSTimeInterval secs = [now timeIntervalSinceDate:self.hireDate];
return secs / 31557600.0; //一年的秒数
} else {
return 0;
}
}
@end
main.m
#import <Foundation/Foundation.h>
//BNREmployee.h中包含BNRPerson.h,所以导入BNREmployee.h即可
//#import "BNRPerson.h"
#import "BNREmployee.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
//子类的实例可以毫无疑问的代替父类的实例,因为它继承父类的所有东西
BNRPerson *mikey = [[BNREmployee alloc] init];
//
[mikey setHeightInMeters:96];
[mikey setWeightInKilos:1.8];
//
float height = [mikey heightInMeters];
int weight = [mikey weightInKilos];
NSLog(@"mikey is %.2f meters tall and weights %d kilograms",height,weight);
//
float bmi = [mikey bodyMassIndex];
NSLog(@"mikey has a BMI of %f",bmi);
}
return 0;
}
对main.m做更新,可以更好的利用BNREmployee类。
#import <Foundation/Foundation.h>
//#import "BNRPerson.h"
#import "BNREmployee.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
//创建一个实例
BNREmployee *mikey = [[BNREmployee alloc] init];
//
[mikey setHeightInMeters:96];
[mikey setWeightInKilos:1.8];
//进行属性设置
mikey.employeeID = 12;
mikey.hireDate = [NSDate dateWithNaturalLanguageString:@"Aug 2nd,2010"];
//
float height = [mikey heightInMeters];
int weight = [mikey weightInKilos];
NSLog(@"mikey is %.2f meters tall and weights %d kilograms",height,weight);
NSLog(@"Employee %u hired on %@", mikey.employeeID, mikey.hireDate);
//
float bmi = [mikey bodyMassIndex];
NSLog(@"mikey has a BMI of %f",bmi);
//计算工作年限
double years = [mikey yearsOfEmployment];
NSLog(@"BMI of %.2f,has worked with us for %.2f years",bmi,years);
}
return 0;
}
1、覆盖方法
子类可以实现父类的同名方法,从而覆盖掉父类的方法。比如BNREmployee类覆盖掉BNRPerson类的boyMassIndex方法。
//这样子类实例调用bodyMassIndex方法时,都会返回19.0
- (float) bodyMassIndex
{
return 19.0;
}
只需要在.m文件中写出实现,不需要再.h文件中声明。覆盖方法的时候只能改变方法的实现,无法改变它的声明方式。
2、Super
覆盖一个方法的时候,子类可以利用父类的实现。
- (float) bodyMassIndex
{
//调用父类的方法
float normalBMI = [super bodyMassIndex];
return normalBMI * 0.9;
}
3、继承层次
给对象发送消息的时候,对象就会查询是否有该消息名的方法。如果没有,就会继续查询它的父类。对象会沿着继承链向上查询,直到找到名为消息名的方法,或者到达继承链的顶端为止。
4、description方法和%@转换说明
格式说明符%@让对象描述自己,处理%@时,程序会先向相应的指针变量所指的对象发送description消息。description方法返回一个描述类实例的字符串。
用NSString覆盖description方法。
- (NSString *) description
{
return [NSString stringWithFormat:@"<Employee %d>",self.employeeID];
}