Object C 繼承

在OC 中有父類和子類的概念,沒有父類(超類->super class)的類位於類層次結構的最頂層,成爲根(root)類,OC中可以定義自己的根類,但不建議這麼做。定義了一個新類,會從父類繼承些屬性。比如,父類的非私有變量和方法都會成爲新類定義的一部分,子類可以直接訪問這些方法和實例變量。
下面舉個例子,首先定義一個類ClassA,再定義一個類ClassB:
#import <Foundation/Foundation.h>

//ClassA的聲明
@interface ClassA : NSObject
{
    int x;
}

-(void) initVar;
@end

//ClassA 的實現
@implementation ClassA

-(void) initVar
{
    x = 100;
}
@end

//聲明ClassB
@interface ClassB : ClassA

-(void) printVar;

@end

@implementation ClassB

-(void) printVar
{
    NSLog(@"x=%i",x);
}

@end
ClassA ,ClassB ,NSObject 幾個類之間的關係如下圖:

如上圖: NSObject 是ClassA和ClassB的父類。由於ClassB是ClassA的子類,因此它繼承了ClassA的共有實例變量和方法:

其實像alloc , init 方法在使用時都未定義過,使用的時候都是從NSObject類中繼承過來的。
注意:1.類的每個對象都擁有自己的實例變量,即使這些實例變量是繼承來的。
 2.繼承的概念是作用於整個繼承鏈的。
1.通過繼承添加新方法
(1)我們想寫一個矩形的類, 同時寫一個正方形類作爲矩形的子類,下面爲Recangle, Square的生命和實現代碼:
#import <Foundation/Foundation.h>

@interface Rectangle : NSObject

@property int width, height;
-(int) area;
-(int) perimeter;

@end
//Rectangle.m
#import "Rectangle.h"

@implementation Rectangle

@synthesize width, height;

-(void)setWidth:(int)w andHeight:(int)h
{
    width = w;
    height = h;
}

-(int)area
{
    return width * height;
}

-(int)perimeter
{
    return 2*(width + height);
}
@end
//Square.h
#import <Foundation/Foundation.h>
#import "Rectangle.h"

@interface Square : Rectangle

-(void) setSide: (int)s;
-(int) side;
@end

//Square.m
#import "Square.h"

@implementation Square: Rectangle

-(void) setSide: (int)s
{
    [self setWidth: s andHeight: s];
}
-(int) side
{
    return self.width;
}
@end
#import <Foundation/Foundation.h>
#import "Square.h"

int main ()
{
    @autoreleasepool {
        Square *mySquare = [[Square alloc] init];
        
        [mySquare setSide:10];
        NSLog(@"Square s = %i", [mySquare side]);
        NSLog(@"Area = %i, Perimeter = %i", [mySquare area], [mySquare perimeter]);
    }
    return 0;
}
square方法雖然是Rectangle類的子類,但是因爲width是私有的,故需要通過繼承Rectangle的set方法來或缺。這種定義square類的方式是OC中的基本技術,即擴展自己或其他人以前實現的類,使其適合自己的需求。

2.重寫方法
前面提到過,不能通過繼承刪除或減少方法,但可以利用重寫更繼承方法的定義。所謂重寫即子類重現父類中的某個方法,覆蓋父類以前的方法(方法的返回型和參數數目都要相同)。
下面的例子說明重寫
<span style="font-size:14px;">#import <Foundation/Foundation.h>

//ClassA的聲明
@interface ClassA : NSObject
{
    int x;
}

-(void) initVar;
@end

//ClassA 的實現
@implementation ClassA

-(void) initVar
{
    x = 100;
}
@end

//聲明ClassB
@interface ClassB : ClassA

-(void) initVar;
-(void) printVar;

@end

@implementation ClassB

-(void) initVar
{
    x =200;
}
-(void) printVar
{
    NSLog(@"x=%i",x);
}

@end

int main ()
{
    @autoreleasepool {
        ClassB *b = [[ClassB alloc] init];
        
        [b initVar];
        [b printVar];
    }
    return 0;
}</span>
運行結果x = 200; 顯然ClassB中的initVar 方法覆蓋了父類中的initVar方法。

總結
(1)繼承的優點:
a. 抽取重複代碼,簡歷類之間的關係。
b. 子類可以擁有父類中所有成員變量和方法。
c. 基本上所有類的根類都是NSObject。
 (2)注意:
a. 父類必須聲明在子類前面。
b. 不允許子類和父類有相同名稱的成員變量。
c. 調用某個方法時,優先去當前類中找,如果找不到,去父類中找。
 (3)重寫:
子類重新實現父類中的某個方法,覆蓋父類以前的方法。
 (4)什麼時候創建子類:
a. 希望繼承一個類的函數,或許加入一些新的方法和實例變量。
b. 希望創建一個類的特別版本(圖形對象的特定類型)。
c. 希望通過覆寫一個或多個方法來改變類的默認行爲。
發佈了42 篇原創文章 · 獲贊 9 · 訪問量 28萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章