NSCopying和继承

Dee*_*pak 5 objective-c

请看下面的代码:-------.h

@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
Run Code Online (Sandbox Code Playgroud)

---------- .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
Run Code Online (Sandbox Code Playgroud)

运行此代码::::::

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];
Run Code Online (Sandbox Code Playgroud) #

我不知道代码有什么问题请帮帮我.提前致谢.

谢谢迪帕克

Mar*_*ius 30

您的基本copyWithZone:方法应如下所示:

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

    // copy base members:
    // ...

    return base;
}
Run Code Online (Sandbox Code Playgroud)

您的派生copyWithZone:方法应如下所示:

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

    // copy derived members:
    // ...

    return derived;
}
Run Code Online (Sandbox Code Playgroud)

另外,请确保您正在制作强引用的深层副本和弱引用的浅层副本.因此,对于例如类型的复制成员NSStringNSArray(每个具有强引用成员,一个具有弱成员)执行:

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;
Run Code Online (Sandbox Code Playgroud)

(通常还会分配/保留弱成员并复制强变量.)

请注意,因此您不应使用initWithMyself:类型方法来复制数据.

  • 基类allocWithZone中的`[self class]`为+1.注定没有那个! (2认同)

Eri*_*tin 1

首先,您的测试代码很糟糕,因为您在 8 位整数中设置了保存数 2001。其次,您的代码无法运行,因为您尝试在 BankAccount 而不是 Saving 对象上调用 setSavingNumber:andOffer: ,因此在运行时无法找到此方法的选择器。感谢大卫指出这一点。

在实现 BankAccount::copyWithZone 时,您使用了 alloc-init 并返回了很好的对象。实现 Savings::copyWithZone 时,您可以调用 super copyWithZone。您得到的是 BankAccount 类型的对象,因此您不能对其使用 setSavingNumber:andOffer: 。由于您在基类中使用了 alloc-init,因此您还应该在 Savings 类中使用 alloc-init 和 setMethods。

为了避免重复代码,我建议在 BankAccount 中实现 initWithBankAccount ,并在 Savings 中实现相同的 initWithBankAccount 。

然后在 copyWithZone 中,您将拥有

return [[BankAccount allocWithZone:zone] initWithBankAccount:self];
Run Code Online (Sandbox Code Playgroud)

return [[Savings allocWithZone:zone] initWithSavings:self];
Run Code Online (Sandbox Code Playgroud)

尽管您必须确保在 initWithSavings 中调用

self = [super initWithBankAccount:savings];
Run Code Online (Sandbox Code Playgroud)

或者直接调用 init 并复制基本成员初始化。

查看内存管理编程指南中的实现对象复制。