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