OC语言--继承、点语法、类别
1 继承
1.0 面向对象的三个基本特征:1.封装2.继承3.多态
1.1 生活中的继承
-》继承的生活逻辑
a.继承遗产:预先给予,不需要自行再建
b. 人类 父类
男人和女人 子类
乔布斯 和章子怡 对象
-》继承的概念:继承(也被称为派生)。
父类拥有的属性和方法,子类直接获得,这个过程叫做继承。
子类在父类基础上,衍生出了自己独有的属性和方法,称为派生。
-》父子类的各种称呼:
父类 parentClass 超类 supperClass 基类baseClass
子类 childClass 子类 subClass 派生类derivedClass
1.2 代码中的继承
-》继承的基本语法
a.语法形式
@interface 子类名 : 父类名
@interface Person :NSObject//在oc中任何一个类都必须继承一个类,也就是说,每个必须单继承
@end
b.继承之后
子类可以使用父类的所有方法
子类可以获得父类非私有的成员变量
c.类字段和成员方法访问控制
@interface Person : NSObject//NSObject 根类 { @protected//受保护的:, // 子类继承父类之后, // 子类可以直接使用父类的受保护成员变量 int _age; @public//公有的:类内和类外的函数 //都可以直接使用公有的成员变量 //这将一定程度上破坏对象信息的隐藏性 int _height; @private//私有的: 类内减方法可以直接使用私有的 // 类外的方法不能直接使用, // 但是可以通过实例方法间接访问和使用, // 子类继承父类之后, // 子类可以通过父类的方法间接使用父类私有的变量 int _money; }
成员方法:没有@private @protected @public 这样的访问控制
OC中子类继承父类之后就拥有了父类的方法
注:
1、OC中的方法类似于C++中的虚函数
2、OC中是没有类似于C++的private作用域的私有方法,
但是可以通过其他方式实现
-》继承在内存中的体现
子类继承父类之后 子类对象的构成:
a.继承的父类的成员变量
b.子类自己特有的成员变量
-》重写(Override覆盖)
a.子类从父类继承的方法,有时候不适合子类,子类可以重写这个方法
b.重写就是重新实现一遍父类的方法(方法名一样 实现内容不同)
c.子类重写父类方法之后,子类对象最终执行的是子类重写之后的方法
-》多态
a.其实多态就是指,同一个接口不同的实现//重写
b.从OC消息机制看:给不同的对象发送相同的消息,反应不同
-》什么时候使用继承
a.创建大量相似的类
【例】创建象棋中的棋子,车马士象炮。
可以先创建棋子类,作为父类。
b.继承一个官方类,添加属性和方法,创建一个更符合当前工程的新类。
c.用继承方式统一接口(不常用)
-》继承的作用
代码重复利用,节约资源提高效率
-》类簇
a.类簇是基础框架中一种常见的设计模式,基于抽象工厂模式的思想。
它将若干相关的私有具体工厂子类集合到抽象超类之下;
b.类簇将一些私有的、具体的子类组合在一个公共的、抽象的超类下面,
以这种方法来组织类可以简化一个面向对象框架的公开架构,
而又不减少功能 的丰富性;
c.NSString NSArray NSDictionary NSNumber都是[类簇/工厂类]
不能被继承,即使被继承,也不能使用父类的方法。
2 点语法和属性关键词@property 的使用
-》点语法与setter/getter 的关系
点语法和@property 关键字的使用,
是对于setter/getter方法的语法替代;
其原理,类似 C 语言中的,是在程序的编译阶段被替代。
该替代,为文本替代,不去检查程序的逻辑语义。
a.只要一个类有符合要求的setter/getter方法那么就可以使用'.'操作
b.xiaohong.name = @"xiaohong"; 这里实际上调用的是setter方法
NSString *nameString = xiaohong.name;这里实际上调用的是getter方法
c. id 类型不能直接使用点操作(需要强制类型转换)
-》属性@property
a. @property自动声明setter和getter方法
@synthesize自动实现setter和getter方法
b. @property NSUInteger x;创建下述两个方法
- (void)setX:(NSUInteger)x;
- (NSUInteger)x;
@synthesize x = _x;//实现下述两个方法 Xcode4.6以后可以省略
- (void)setX:(NSUInteger)x
{
_x = x;
}
- (NSUInteger)x
{
return _x;
}
-》属性修饰符
//只读修饰符
//只有getter方法,没有setter方法
@property (readonly) NSString * name;
//直接赋值修饰符(缺省)
@property (assign) NSString * name;
//读写修饰符(缺省)
//同时创建set方法和get方法
@property (readwrite) NSString * address;
//原子操作修饰符(缺省)
@property (atomic) NSString * group;
//非原子操作
@property (nonatomic) NSString * grade;
//多个属性修饰符,需要用逗号隔开
@property (nonatomic, readonly, getter = birth) NSString * birthDay;
//给set方法和get方法起别名
@property (getter = personAge, setter = setAgi:) int age;
3. 类别/类目 Category
(1)增补既有类的方法,它是具名
(2)不能添加新的属性
(3)包括NSString,NSDictionary,NSArray,NSNumber内所有的类都能扩展,都能使用category
-》类别的基本语法
//类别的声明部分 @interface NSString(Print) -(void)print;//增加的新方法(不能有成员变量的声明) ... @end //类别实现部分 @implementation NSString(Print) -(void)print{ } … @end
注:一旦使用类别给已有的类增补方法,那么这个类的对象就可以使用这个方法
-》.类别功能:
a. 可以给已有/ 系统原生的类增补方法
b.可以对类的方法进行分类管理,
可以将类的实现分散到多个不同文件或多个不同框架中。
-》使用类别需要注意的问题
a.类别中不能添加成员变量
b.使用类别增补的方法须导入类别头文件
c.父类类别中的方法,子类也可以用
-》类扩展/匿名类别 (class extend)
当不想对外公开一些类的方法时,我们可以使用类扩展
a.类扩展的基本语法
类扩展的声明写在.m文件中
@interface Person()//没有名字 - (void)song; @end @implementation Person - (void)song{ NSLog(@"hello"); } @end
注:
类扩展只有声明部分,没有实现部分 。
类扩展中声明的方法需要在类的实现部分实现
b.类扩展的功能
1.可以实现私有方法
2.方便程序员调用不公开的方法
3.可以声明成员变量
eg.示例代码
Account.h文件
#import <Foundation/Foundation.h> #define RATE 0.0325 @interface Account : NSObject{ NSUInteger _uid;//用户账号 NSString* _upasswd;//用户密码 double _uamount;//账户余额 double _uperiod;//储蓄时间 double _rate;//一年期的存款利率 } @property (assign,nonatomic) NSUInteger uid; @property (copy,nonatomic) NSString* upasswd; @property (assign,nonatomic) double uamount; @property (assign,nonatomic) double uperiod; @property (assign,nonatomic) double rate; - (void)deposit:(double)money;//存款 - (double)withdraw:(double)money;//提款 - (double)settlementOnWithdraw:(double)money;//取款时结算利息 - (double)settlementUponYear;//年度结算利息 - (double)interestCaculate;//利息计算 - (double)incomeCaculate;//到期本息收益 + (void)testBySelf;//本类的自测方法 - (id)initWithUid:(NSUInteger)aUid andUpasswd:(NSString*)aUpasswd andUamount:(double)aUamount; @end
Account+currency.h文件
#import "Account.h" @interface Account (currency) - (void)deposit:(double)money withForeignCurrency:(char)type;//存款 - (double)withdraw:(double)money withForeignCurrency:(char)type;//提款 @end
Account.m文件
#import "Account.h" #import "Account+currency.h" //#include "Account_dollar.h" @implementation Account @synthesize uid=_uid; @synthesize uamount=_uamount; @synthesize upasswd=_upasswd; @synthesize rate=_rate; @synthesize uperiod=_uperiod; - (void)deposit:(double)money{ _uamount += money; NSLog(@"存款后的当前账户余额:%.2lf",_uamount); } - (double)withdraw:(double)money{ _uamount += [self settlementOnWithdraw:_uamount]; _uamount -= money; NSLog(@"取款后的当前账户余额:%.2lf",_uamount); return _uamount; } - (double)settlementOnWithdraw:(double)money//取款时结算利息 { double RetMoney = money; return RetMoney *= (_rate * _uperiod); } - (double)settlementUponYear//年度结算利息 { return _uamount *= (1+_rate); } - (double)interestCaculate//到期利息计算 { double interest = 0.0; return interest = _uamount * _rate; } - (double)incomeCaculate//到期本息收益 { double income = 0.0; return income = _uamount*(1+_rate); } + (void)testBySelf//本类的自测方法 { //新建一个账户实例 Account* aAccount = [[Account alloc]init]; //显示账户初始状态 NSLog(@"%@",aAccount); //存款测试 [aAccount deposit:100.00]; NSLog(@"%@",aAccount); //模拟的日期间隔 int n = 36; for(int i=1;i<=n;i++){ aAccount.uperiod = (double)i/(double)365; } //取款测试 [aAccount withdraw:50.00]; NSLog(@"%@",aAccount); //模拟存一笔前,并到一年期 [aAccount deposit:100.00]; //模拟时间流逝 for(int i=n;i<=365;i++){ aAccount.uperiod = (double)i/(double)356; } [aAccount settlementUponYear]; NSLog(@"%@",aAccount); //外币存款 // aAccount.foreign_amount = 1.0; [aAccount deposit:200.00 withForeignCurrency:'$']; } - (id)initWithUid:(NSUInteger)aUid andUpasswd:(NSString*)aUpasswd andUamount:(double)aUamount{ if (self = [super init]) { _rate = RATE; _uperiod = 1/365; _uid = aUid; _upasswd = aUpasswd; _uamount = aUamount; } return self; } -(id)init { return [self initWithUid:1 andUpasswd:@"123456" andUamount:1.0]; } - (NSString *)description { NSString* passwd_des = @"******"; return [NSString stringWithFormat:@"用户账号:%06lu 用户口令:%@ 账户余额:%.2lf(元) 当前定期存款利率(一年期):%.4lf 存储时间:%.2lf(年)", _uid,passwd_des,_uamount,_rate,_uperiod]; } @end
Account+currency.m文件
#import "Account+currency.h" #import "Account_dollar.h" @implementation Account (currency) //外币存款方法 - (void)deposit:(double)money withForeignCurrency:(char)type//存款 { double fa = self.foreign_amount; fa += money; self.foreign_amount = fa; NSLog(@"存款后的当前外币(%c)账户余额:%.2lf",type,self.foreign_amount); } //外币取款方法有 bug,请自行修改正确!!! - (double)withdraw:(double)money withForeignCurrency:(char)type//提款 { self.foreign_amount += [self settlementOnWithdraw:self.foreign_amount]; self.foreign_amount -= money; NSLog(@"取款后的当前外币(%c)账户余额:%.2lf",type,self.foreign_amount); return self.foreign_amount; } @end
Account_dollar.h文件
#import "Account.h" @interface Account (){ char _currency_type; double _foreign_rate; double foreign_amount; } @property (assign) char currency_type; @property (assign) double foreign_rate; @property (assign) double foreign_amount; @end