2010-08-06 60 views
5

請對下面的代碼來看看:------- .HNSCopying和繼承

@interface BankAccount : NSObject<NSCopying> 
{ 
    double accountBalance; 
    long accountNumber; 
    NSString *CustomerName; 
    NSString *AccountType; 
} 

-(void) setAccount: (long) y andBalance: (double) x; 
-(void) setCustomerName: (NSString*) name andAccountType: (NSString*) type; 
-(id)copyWithZone:(NSZone *)zone; 

@end 

@interface Savings : BankAccount 
{ 
    int number; 
    NSString *Offer; 
} 
-(void) setSavingNumber: (uint8_t) num andOffer: (NSString*) offer; 
-(id)copyWithZone:(NSZone *)zone; 
@end 

---------- .M

@implementation BankAccount 

-(void) setAccount: (long) y andBalance: (double) x 
{ 
    accountNumber = y; 
    accountBalance = x; 
} 
-(void) setCustomerName: (NSString*) name andAccountType: (NSString*) type 
{ 
    CustomerName = name; 
    AccountType = type; 
} 

-(id)copyWithZone:(NSZone *)zone 
{ 
    BankAccount *accountCopy = [[BankAccount allocWithZone: zone] init]; 
    [accountCopy setAccount: accountNumber andBalance: accountBalance]; 
    [accountCopy setCustomerName:CustomerName andAccountType:AccountType]; 
    return accountCopy; 
} 

@end 

@implementation Savings 
-(void) setSavingNumber: (uint8_t) num andOffer: (NSString*) offer 
{ 
    number = num; 
    Offer = offer; 
} 

-(id)copyWithZone:(NSZone *)zone 
{ 
    Savings * clone = [super copyWithZone:zone]; 
    [clone setSavingNumber:number andOffer:Offer];************** error ********* 
    return clone; 
} 

@end 

當運行此代碼::::::

Savings* account1; 
Savings* account2; 

account1 = [[Savings alloc] init]; 
[account1 setAccount:10 andBalance:1000.10]; 
[account1 setCustomerName:[NSString stringWithFormat:@"%@",@"Deepak"] andAccountType:[NSString stringWithFormat:@"%@",@"Savings"]]; 
[account1 setSavingNumber:2001 andOffer:@"Bad"];  
account2 = [account1 copy]; 

我不知道什麼是錯的代碼,請幫助我。提前致謝。

感謝 迪帕克

+2

請格式化代碼並提出問題。目前的行爲是什麼,預期會是什麼。 – 2010-08-06 12:30:27

回答

1

好吧第一,你的測試代碼是不好的,因爲你在一個8位整數設定的2001年一保存號。其次,代碼不會運行,因爲您試圖在BankAccount而不是Save對象上調用setSavingNumber:andOffer:因此它在運行時無法找到此方法的選擇器。感謝大衛指出了這一點。

當實現BankAccount :: copyWithZone時,你使用了alloc-init,並且你返回了很好的對象。在實施Savings :: copyWithZone時,您可以調用super copyWithZone。你得到的是一個BankAccount類型的對象,所以你不能使用setSavingNumber:andOffer:就可以了。由於您在基類中使用了alloc-init,因此您還應該在Savings類中使用alloc-init和setMethods。

爲了避免重複代碼,我會推薦在BankAccount中實現一個initWithBankAccount並且在Savings中也是一樣。

然後在copyWithZone,你必須

return [[BankAccount allocWithZone:zone] initWithBankAccount:self]; 

return [[Savings allocWithZone:zone] initWithSavings:self]; 

雖然你必須確保在initWithSavings你打電話或者

self = [super initWithBankAccount:savings]; 

還是你打直init並複製基本成員初始化。

查看Memory management programming guide的Implementing object copy

+0

與C++或C不同,objective-c的動態特性將允許未處理的消息傳遞給對象,但在運行時會失敗(與您提到的編譯相反)。請更新答案以反映這一點。 – David 2010-08-09 14:27:39

+0

在BankAccount的'copyWithZone'中調用'initWithBankAccount:'的問題是它不會將這些成員作爲深度副本返回。這可能會也可能不會給你以後的問題。 – Marius 2011-05-26 18:12:15

+0

當然這很好,如果所有的成員碰巧是弱引用,並且不需要副本。但是請注意,如果您希望在「NSDictionary」中使用類作爲鍵或在「NSSet」中使用它們,則更改排序依賴的值可能會導致問題/錯誤。 – Marius 2011-05-26 19:49:08

28

你的基地copyWithZone:方法應該是這樣的:

-(id)copyWithZone:(NSZone *)zone { 
    // change this line to use [self class] 
    BaseClass *base = [[[self class] allocWithZone:zone] init]; 

    // copy base members: 
    // ... 

    return base; 
} 

派生的copyWithZone:方法應該是這樣的:

-(id)copyWithZone:(NSZone *)zone { 
    DerivedClass *derived = [super copyWithZone:zone]; 

    // copy derived members: 
    // ... 

    return derived; 
} 

還要確保確保你正在強引用淺淺的深層副本弱引用的副本。因此,爲了對NSString類型和NSArray(每一個與強烈引用部件和一個具有弱)的例子拷貝成員做:

derived.strongString = [[strongString copyWithZone:zone] autorelease]; 
derived.weakString  = weakString; 
derived.strArrWStrVals = [[strArrWStrVals copyWithZone:zone] autorelease]; 
derived.strArrWWeakVals = [[[NSArray allocWithZone:zone] 
          initWithArray:strArrWWeakVals] autorelease]; 
derived.weakArray  = weakArray; 

(一般弱成員也被分配/保留和強變量被複制)

請注意,因此,您不應使用initWithMyself:類型的方法來複制數據。

+0

copyWithZone不一定會返回深層副本。看看原型模式。它將NSCopying協議與NSArchiver和NSUnarchiver結合使用,使複製成爲一項簡單的任務。 – 2012-03-19 12:40:13

+2

對於基類allocWithZone中的'[self class]'+1。沒有這個註定! – Echelon 2014-10-24 17:16:31

+1

在許多stackoverflow問題NSCopying解釋,但不知何故,他們錯過了突出使用[自我班]。 – 2016-09-30 08:34:23