目录
一、创建一个新类,命名为BNREmployee,并将其设置为BNRPerson的子类
在创建BNRPerson类的时候,将其声明为了NSObject子类,这意味着BNRPerson实例除了会拥有在BNRPerson中定义的实例变量和方法外,还会拥有在NSObject中定义的实例变量和方法。对此,可以称BNRPerson继承了NSObject的实例变量和方法。
一、创建一个新类,命名为BNREmployee,并将其设置为BNRPerson的子类
在BNREmployee.h文件中增加三个属性,员工的ID、雇佣日期和办公室紧急码。同时声明一个方法,基于员工的雇佣日期来计算员工的工龄。
#import "BNRPerson.h"
NS_ASSUME_NONNULL_BEGIN
@interface BNREmployee : BNRPerson
@property (nonatomic) unsigned int employeeID;
@property (nonatomic) unsigned int officeAlarmCode;
@property (nonatomic) NSDate* hireDate;
- (double) yearOfEmployment;
@end
NS_ASSUME_NONNULL_END
BNREmploy.m实现代码如下:
#import "BNREmployee.h"
@implementation BNREmployee
- (double) yearOfEmployment
{
//判断是否有一个非nil的hireDate
if(self.hireDate) {
NSDate* now = [NSDate date];
//NSTimeInterval是double类型
NSTimeInterval secs = [now timeIntervalSinceDate:self.hireDate];
//根据秒数计算年数
return secs / 31557600.0; //除以每年的秒数
} else {
return 0;
}
}
@end
打开main.m文件,导入BNREmployee.h,创建BNREmplyee的实例对象
#import <Foundation/Foundation.h>
#import "BNREmployee.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
//创建一个BNREmployee的实例
BNRPerson* mikey = [[BNREmployee alloc] init];
//使用存方法给实例变量赋值
mikey.heightInMeters = 1.62;
mikey.weightInKilos = 46;
//使用取方法打印实例变量的值
float height = mikey.heightInMeters;
int weight = mikey.weightInKilos;
NSLog(@"mikey is %.2f meters tall and weights %d kilos", height, weight);
//使用定制的方法打印相应的BMI的值
float bmi = [mikey bodyMassIndex];
NSLog(@"mikey has a BMI of %.2f", bmi);
}
return 0;
}
⚠️main.m中没有导入BNRPerson.h文件。对编译器来说BNREmployee.h包含了#import "#import "BNREmployee.h"这个语句,所以不必再导入一遍。
下面对main.m文件做一些更新,给mikey设置employeeID,然后设置雇佣日期。
#import <Foundation/Foundation.h>
#import "BNREmployee.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
//创建一个BNREmployee的实例
BNREmployee* mikey = [[BNREmployee alloc] init];
//使用存方法给实例变量赋值
mikey.heightInMeters = 1.62;
mikey.weightInKilos = 46;
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 kilos", height, weight);
NSLog(@"Employee %u hired on %@", mikey.employeeID, mikey.hireDate);
//使用定制的方法打印相应的BMI的值和员工工龄
float bmi = [mikey bodyMassIndex];
double years = [mikey yearsOfEmployment];
NSLog(@"BMI of %.2f, has worked with us for %.2f years.", bmi, years);
}
return 0;
}
⚠️:这里做了改变BNREmployee* mikey = [[BNREmployee alloc] init];
二、覆盖方法
通常子类要与父类有所不同。
假设,员工的BMI都是19。在这种情况下,可以覆盖BNREmployee的bodyMassIndex方法。
#import "BNREmployee.h"
@implementation BNREmployee
- (double) yearsOfEmployment
{
//判断是否有一个非nil的hireDate
if(self.hireDate) {
NSDate* now = [NSDate date];
//NSTimeInterval是double类型
NSTimeInterval secs = [now timeIntervalSinceDate:self.hireDate];
//根据秒数计算年数
return secs / 31557600.0; //除以每年的秒数
} else {
return 0;
}
}
//覆盖了父类的方法
-(float) bodyMassIndex
{
return 19.0;
}
@end
覆盖方法只能改变方法的实现,无法概拜年它的声明方式,方法的名称、返回值类型及参数的类型都必须保持相同。
三、supper
覆盖一个方法的时候,子类可以利用父类的实现,而不是整个替换。
假设员工的BMI的值,是在BNRPerson方法的结果基础上乘上0.9并返回新的值,就可以使用super指令。
//覆盖了父类的方法
-(float) bodyMassIndex
{
float normalBMI = [super bodyMassIndex];
return normalBMI * 0.9;
}
三、继承层次
NSObject虽然有很多的方法,但是只有一个实例变量:isa指针。任何一个对象的isa指针都会指向创建该对象的类。
例如:创建了一个BNRPerson实例,那么isa就是BNRPerson,如果创建了一个NSString实例,那么isa就是NSString。
给对象发送消息的时候,对象就会查询是否有该消息名的方法。
如果没有就继续查询它的父类,以此类推。直到继承链的顶端为止。
如果找不到,程序就会报错。
但是如果使用了super,就等于告诉对象“运行指定的方法,但是从对象的父类开始查找”。
五、description方法和%@转换说明
在调用NSLog()的时候,我们使用了%@让对象描述自己。
处理%@时,程序会向相应的指针变量所致的对象发送description消息。
description方法灰返回一个描述类实例的字符串。
下面我们在BNREmployee.m文件中,覆盖description方法。
#import "BNREmployee.h"
@implementation BNREmployee
……
- (NSString*) description
{
return [NSString stringWithFormat:@"<Emplyee %d>", self.employeeID];
}
@end
在main.m中进行使用。
//NSLog(@"%@ hired on %@", mikey, mikey.hireDate);
#import <Foundation/Foundation.h>
#import "BNREmployee.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
//创建一个BNREmployee的实例
BNREmployee* mikey = [[BNREmployee alloc] init];
//使用存方法给实例变量赋值
mikey.heightInMeters = 1.62;
mikey.weightInKilos = 46;
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 kilos", height, weight);
NSLog(@"%@ hired on %@", mikey, mikey.hireDate);
//使用定制的方法打印相应的BMI的值和员工工龄
float bmi = [mikey bodyMassIndex];
double years = [mikey yearsOfEmployment];
NSLog(@"BMI of %.2f, has worked with us for %.2f years.", bmi, years);
}
return 0;
}