標籤:objective-c 繼承 ios
一、繼承
繼承的上層:父類,繼承的下層:子類。繼承是單向的,不能相互繼承。繼承具有傳遞性:A繼承於B,B繼承於C,A具有B和C的特徵和?為。子類能繼承父類全部的特徵和行為。
例題
打殭屍。需求:
1、定義普通殭屍類:
執行個體變數:殭屍總血量、殭屍每次失血量。
方法:初始化方法(總血量)、被打擊失血、死亡。
2、定義路障殭屍類:
執行個體變數:殭屍總血量、殭屍每次失血量,道具,弱點。
方法:初始化方法(總血量)、被打擊失血、失去裝備、死亡。
3、定義鐵桶殭屍類:
執行個體變數:殭屍總血量、殭屍每次失血量,道具,弱點。
方法:初始化方法(總血量)、被打擊失血、失去裝備、死亡。
4、在main.m中建立普通殭屍對象,設定總血量50,每次失血量為 3,沒有道具。
5、在main.m中建立路障殭屍對象,設定總血量80,每次失血量為 2,設定道具為路障。
6、在main.m中建立鐵桶殭屍對象,設定總血量120,每次失血量為 1,設定道具為鐵桶。
如果定義三個類:普通殭屍、路障殭屍、鐵桶殭屍。它們會有很多重複的執行個體變數和方法,這不僅是體力活,而且也不科學。物件導向提供了繼承文法,能?大簡化代碼。把公用的方法和執行個體變數寫在父類裡,子類只需要寫?己專屬的執行個體變數和方法即可。繼承既能保證類的完整,又能簡化代碼。
繼承實現
#import <Foundation/Foundation.h> /* 子類 */ /* 父類 */@interface OrdinaryZombie : NSObject@end
#import "OrdinaryZombie.h" /* 子類 */ /* 父類 */@interface RoadblockZombie : OrdinaryZombie@end
繼承特點
Objective-C中只允許單繼承。沒有父類的類稱為根類,Objective-C中的根類是NSObject(祖宗)。
繼承的內容:所有執行個體變數和方法。如果子類不滿意父類方法的實現,可以重寫(overwrite)父類的方法。
繼承樹
繼承中?法的執行
self、super
self和super是Objective-C語言中的關鍵字。
super是編譯器指令,並非對象。
作用:給super發訊息,可以執?父類中實現的方法。
子類可以重寫父類的方法,即:子類既有?己的實現,?有父類繼承下來的實現,如果想使用父類的實現,向super發送訊息。
self作用:調用自身的方法和屬性,始終代表調用方法的對象。
self和super使用的簡單範例程式碼如下:
- (instancetype)initWithName:(NSString *)name sex:(NSString *)sex{ /* * 詳細解釋[super init] * 父類中定義的執行個體變數通過向super請求初始化方法來得到初始化 * 向super請求初始化方法的訊息串連起了所有繼承樹上的對象 * 父類的變數會比子類的變數先得到初始化 * 例如: CollegeStudent對象在初始化時, 會依次對NSObject, Student, CollegeStudent進行初始化 * 關於初始化方法, 請查閱本博文下面內容 */ self = [super init]; if (self) { _name = name; _sex = sex; } return self;}
二、初始化方法
使用Objective-C建立對象分為兩步:
- 記憶體配置(開闢空間):為新對象動態分配一段記憶體位址。
- 初始化:為這段記憶體空間賦初始值。
初始化方法在對象的整個生命週期裡只使用一次。初始化方法命名一般以init開頭;初始化方法可以在對象建立的時候給執行個體變數賦初值;初始化方法的傳回值只能是id(或instancetype)或本類對象,不能是void。一個類可以有多個初始化方法。
完整的初始化方法,範例程式碼如下:
- (instancetype)initWithName:(NSString *)name sex:(NSString *)sex{ // 給super發送init訊息: 即執行父類中實現的init方法 self = [super init]; if (self) { // 初始化設定 _name = name; _sex = sex; } // 返回初始化完成的對象 return self;}
注意:
學習繼承之前,類與類之間沒有關聯,因此初始化方法沒有self = [super init];
字樣,從而為執行個體變數逐一賦值。
學習繼承之後,?類中聲明了共有的執行個體變數。作為父類,應該有自己的初始化方法,為這些共有的執行個體變數賦初值。
子類定義了除父類中公用執行個體變數之外的執行個體變數。在?身的初始化方法中,優先向super發送init訊息,初始化公開變數,初始化成功之後,再初始化?身特有變數,從而完成全部執行個體變數的初始化。
初始化過程
- 子類的初始化方法中,優先調?父類的初始化方法。
- ?類的初始化?法中再調用其父類的初始化方法,依次往上調用,直至NSObject類。
- 處於最上層的初始化完成之後,回到第二層的初始化方法中,完成第二層的初始化。第二層的初始化完成之後,回到第三層的初始化方法中,依次執?初始化方法,直到本類的初始化方法完成。
初始化?法的特徵
三、便利構造器
便利構造器在初始化方法的基礎上進行了封裝,即封裝了對象的建立過程。便利構造器是“+”號方法,返回 本類型 的執行個體,方法名以類名開頭。可以有0到多個參數。內部實現,封裝了alloc和初始化方法。使?起來更加簡潔。
便利構造器的實現
1.聲明和實現便利構造器。
+ (instancetype)personWithName:(NSString *)name sex:(NSString *)sex;+ (instancetype)personWithName:(NSString *)name sex:(NSString *)sex{ Person *person = [[Person alloc] initWithName:name sex:sex]; return person;}
2.使?便利構造器建立對象。
Person *person = [Person personWithName:@"小紅" sex:@"女"];
其實,便利構造器的便利不僅是代碼量的減少,也是對記憶體操作的便利,如果用便利構造器建立了一個對象,則在使用完畢後不用去釋放該對象,出了自動釋放池後,對象被自動銷毀,在自動釋放池銷毀之前,我們持有對象,不用理會什麼時候釋放該對象(這是Objective-C記憶體管理的內容,博主會在後續的博文中詳細說明)。
附錄開篇例題“打殭屍”的代碼實現
本例題利用繼承實現,題目要求較為簡單,請仔細閱讀代碼。
普通殭屍類 OrdinaryZombie.h 代碼如下:
#import <Foundation/Foundation.h>@interface OrdinaryZombie : NSObject{@protected NSInteger _fullOfBlood; /* 總血量 */ NSInteger _lossOfBlood; /* 每次失血量 */ NSString *_equipment; /* 道具 */ NSString *_weakness; /* 弱點 */}/* 執行個體變數setter, getter方法 */- (void)setFullOfBlood:(NSInteger)fullOfBlood;- (NSInteger)fullOfBlood;- (void)setLossOfBlood:(NSInteger)lossOfBlood;- (NSInteger)lossOfBlood;- (void)setEquipment:(NSString *)equipment;- (NSString *)equipment;- (void)setWeakness:(NSString *)weakness;- (NSString *)weakness;/* 初始化方法(總血量) */- (id)initWithBlood:(NSInteger)fullOfBlood;/* 被打擊失血 */- (void)attacked;/* 死亡 */- (void)death;/* 失去裝備 */- (void)loseEquipment;@end
普通殭屍類 OrdinaryZombie.m 代碼如下:
#import "OrdinaryZombie.h"@implementation OrdinaryZombie- (void)setFullOfBlood:(NSInteger)fullOfBlood{ _fullOfBlood = fullOfBlood;}- (NSInteger)fullOfBlood{ return _fullOfBlood;}- (void)setLossOfBlood:(NSInteger)lossOfBlood{ _lossOfBlood = lossOfBlood;}- (NSInteger)lossOfBlood{ return _lossOfBlood;}- (void)setEquipment:(NSString *)equipment{ _equipment = equipment;}- (NSString *)equipment{ return _equipment;}- (void)setWeakness:(NSString *)weakness{ _weakness = weakness;}- (NSString *)weakness{ return _weakness;}- (id)initWithBlood:(NSInteger)fullOfBlood{ _fullOfBlood = fullOfBlood; return self;}- (void)attacked{ _fullOfBlood -= _lossOfBlood; if (_fullOfBlood <= 0) { _fullOfBlood = 0; } NSLog(@"剩餘血量: %ld", _fullOfBlood);}- (void)death{ NSLog(@"普通殭屍, 死亡");}- (void)loseEquipment{ NSLog(@"失去裝備");}@end
路障殭屍類 RoadblockZombie.h 代碼如下:
#import "OrdinaryZombie.h"@interface RoadblockZombie : OrdinaryZombie@end
路障殭屍類 RoadblockZombie.m 代碼如下:
#import "RoadblockZombie.h"@implementation RoadblockZombie- (void)death{ NSLog(@"路障殭屍, 死亡");}- (void)loseEquipment{ NSLog(@"路障殭屍"); [super loseEquipment];}@end
鐵桶殭屍類 MetalBucketZombie.h 代碼如下:
#import "OrdinaryZombie.h"@interface MetalBucketZombie : OrdinaryZombie@end
鐵桶殭屍類 MetalBucketZombie.m 代碼如下:
#import "MetalBucketZombie.h"@implementation MetalBucketZombie- (void)death{ NSLog(@"鐵桶殭屍, 死亡");}- (void)loseEquipment{ NSLog(@"鐵桶殭屍"); [super loseEquipment];}@end
main.m 代碼如下:
#import <Foundation/Foundation.h>#import "OrdinaryZombie.h"#import "RoadblockZombie.h"#import "MetalBucketZombie.h"int main(int argc, const char * argv[]) { @autoreleasepool { /* 普通殭屍 */ OrdinaryZombie *ordZom = [[OrdinaryZombie alloc] initWithBlood:50]; /* 每次失血量 */ [ordZom setLossOfBlood:3]; while (1) { if ([ordZom fullOfBlood] == 0) { [ordZom death]; break; } [ordZom attacked]; } /* 路障殭屍 */ RoadblockZombie *roadZom = [[RoadblockZombie alloc] initWithBlood:80]; /* 每次失血量 */ [roadZom setLossOfBlood:2]; /* 裝備類型 */ [roadZom setEquipment:@"路障"]; while (1) { /* 如果剩餘50滴血 */ if ([roadZom fullOfBlood] <= 50) { /* 失去裝備 */ [roadZom loseEquipment]; /* 失血量設定成普通殭屍 */ [roadZom setLossOfBlood:[ordZom lossOfBlood]]; break; } [roadZom attacked]; } while (1) { if ([roadZom fullOfBlood] == 0) { [roadZom death]; break; } [roadZom attacked]; } /* 鐵桶殭屍 */ MetalBucketZombie *metalZom = [[MetalBucketZombie alloc] initWithBlood:120]; /* 每次失血量 */ [metalZom setLossOfBlood:1]; /* 裝備類型 */ [metalZom setEquipment:@"鐵桶"]; while (1) { /* 如果剩餘50滴血 */ if ([metalZom fullOfBlood] <= 50) { /* 失去裝備 */ [metalZom loseEquipment]; /* 失血量變成普通殭屍 */ [metalZom setLossOfBlood:[ordZom lossOfBlood]]; break; } [metalZom attacked]; } while (1) { if ([metalZom fullOfBlood] == 0) { [metalZom death]; break; } [metalZom attacked]; } } return 0;}
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
Objective-C學習筆記_繼承、初始化方法、便利構造器