2014-01-26 177 views
-1

我要檢查,如果一個子類的以下實現是正確的目標C.超類初始化

首先代碼父父寫的Objective C的子類:

#import "Employee.h" 

    @implementation Employee 

    -(id)init 
    { 
    return [self initEmployee:(NSString *)@"" withId:(NSString *)0]; 
    } 

    -(id)initEmployee:(NSString *)theName withId:(NSString *)theId 
    { 
     self = [super init]; 
     if (self) { 
      _name = theName; 
      _EmpId = theId; 
     } 
     return self; 
    } 

    @end 

然後子類。

#import "FullTimeEmp.h" 

@implementation FullTimeEmp 

-(id)init 
{ 
    return [self initEmployee:(NSString *)@"" 
         withId:(NSString *)@"" 
        andSalary:(NSNumber *)0 
        withBonus:(NSNumber *)0]; 
} 

-(id)initEmployee:(NSString *)theName 
      withId:(NSString *)theId 
     andSalary:(NSNumber *)theSalary 
     withBonus:(NSNumber *)theBonus 
{ 
    self = [super initEmployee:(NSString *)theName withId:(NSString *)theId]; 
    if (self) { 
     self.salary = theSalary; 
     self.bonus = theBonus; 
    } 
    return self; 
} 

@end 

這運行正常,但我一直沒能確認這是做了正確的方式,使用:

自我= [超級initEmployee:(的NSString *)theName withId:(的NSString * )theId];

在繼承超類部分(Name和ID),然後是子類部分的子類中,指定組成Full Time Employee對象的子類添加(Salary和Bonus)。

我讀過所有關於我們使用自己的理由= [超級初始化],但已很難找到如何在子類的初始化是在我的書我還是在網上編碼很好的例子。

+3

**爲什麼**哦,爲什麼所有這些多餘的,醜陋的,不可讀的,不正確的演員? :((((( – 2014-01-26 21:15:33

+1

請閱讀[* Cocoa的編碼指南:命名方法*](https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/CodingGuidelines/Articles/NamingMethods.html)。Better名字是'initWithName:employeeId:'和'initWithName:employeeId:salary:bonus:'。 –

回答

0

你有正確的想法儘可能初始化去。你基本上只需要以某種方式正確地初始化超類。你不做到這一點正是這樣在您的子類,基本上是與一些其他成員的超類,但在這種情況下,它似乎是適當的。你可能有一個子類,其中,例如,theId或其他一些領域將永遠是該子類,在這種情況下,你不需要爲它傳遞一個值的子類的初始化值相同。只要你以最適合你的情況的方式初始化超類,你應該是好的。

但是,你似乎是混亂的方法簽名和方法調用,或發送消息的語法。這:

self = [super initEmployee:(NSString *)theName withId:(NSString *)theId]; 

和類似的應該只是這樣的:

self = [super initEmployee:theName withId:theId]; 

當你定義一個方法,你需要這些東西(NSString *)告訴編譯器是什麼類型的每一個你的論點是,但是當你正在調用方法/發送一個消息,你已經有一個已經有一個已知類型的參數的對象,所以你不需要它。你實際上完成這裏是鑄造NSString *NSString *,這顯然是多餘的。

編輯:由於格熱戈日提到,一般最好是直接通過自己的實例變量訪問你的初始化方法的性能,即代替:

self.salary = theSalary; 

,而不是做:

_salary = theSalary; 

假設你還沒有用不同的名字來合成它。一個很好的理由是因爲子類可以重寫屬性的setter方法,這可能會導致非常不可預測的行爲。通常,在部分構建狀態下發送消息到self應避免,因爲這樣做會產生副作用。顯然,如果你設置一個由超類定義的屬性,並且你沒有訪問實例變量的權限,或者你正在使用延遲初始化,那麼除了使用setter外沒有其他選擇在這裏初始化它),但這不是你在這個例子中的。

編輯2:另外,跟這個有幾點:

-(id)init 
{ 
    return [self initEmployee:(NSString *)@"" 
         withId:(NSString *)@"" 
        andSalary:(NSNumber *)0 
        withBonus:(NSNumber *)0]; 
} 

首先,你不必覺得有必要提供直init方法,如果它沒有任何意義,以對這些默認值的東西。如果你確定有一個沒有姓名和ID的僱員,那麼很好,但如果你只用實際的數據初始化你的一個班級是有意義的,那麼不要爲沒有重寫init甚至關於如果你真的想阻止人們使用它,就會拋出異常。

其次,NSNumber是一個對象,所以當你嘗試直0分配給它,它是相當於指針設置爲nil,而不是創建一個對象可言,這可能不是你想要的這裏。要真正零值創建NSNumber S,你想使用你的NSString做同樣的方式文字,像這樣(這裏也去掉石膏):

-(id)init 
{ 
    return [self initEmployee:@"" 
         withId:@"" 
        andSalary:@0 
        withBonus:@0]; 
} 

或只使用常規int代替NSNumber如果你不需要它們是對象。

+0

添加一條關於不使用self和直接_var的註釋 - 它可能導致不保留參數 - 我相信他現在知道那 –

+0

@GrzegorzKrukowski:我添加了一個註釋,好點:) –

+0

感謝@PaulGriffiths&GrzegorzKrukowski對我的編碼做出了非常全面的迴應,現在我已經很好地解釋清楚了,正如我之前提到的,我發現很難找到一些具體的例子如何正確使用。 – irishetcher

0

作爲更新我在OP的問題,並幫助其他人誰可能這裏有同樣的困惑是我的代碼重新雷農按所給的建議是:

#import "Employee.h" 

@implementation Employee 

-(id)initEmployee:(NSString *)theName withId:(NSString *)theId 
{ 
    self = [super init]; 
    if (self) { 
    _name = theName; 
    _EmpId = theId; 
    } 
return self; 
} 

@end 

而且

#import "FullTimeEmp.h" 

@implementation FullTimeEmp 

-(id)initEmployee:(NSString *)theName 
      withId:(NSString *)theId 
     andSalary:(NSNumber *)theSalary 
     withBonus:(NSNumber *)theBonus 
{ 
    self = [super initEmployee:theName withId:theId]; 
    if (self) { 
     _salary = theSalary; 
     _bonus = theBonus; 
    } 
return self; 
} 

-(NSNumber *)calcPay 
{ 
    NSNumber *pay; 
    pay = [NSNumber numberWithFloat:([self.salary floatValue] + [self.bonus floatValue])]; 
    return pay; 
} 


@end