Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSCopying & Inheritance

Tags:

objective-c

Please have a look on following code :------- .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

---------- .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

When run this code::::::

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];
#

i dont know what is wrong with the code please help me. thanks in advance.

Thanks Deepak

like image 866
Deepak Avatar asked Aug 06 '10 11:08

Deepak


People also ask

What is NSCopying?

The copy() method comes from NSCopying -- a protocol built to do exactly what it implies: giving objects the ability to generate copies of themselves.

What is Nsobject in iOS?

The root class of most Objective-C class hierarchies, from which subclasses inherit a basic interface to the runtime system and the ability to behave as Objective-C objects. iOS 2.0+ iPadOS 2.0+ macOS 10.0+ Mac Catalyst 13.1+ tvOS 9.0+ watchOS 2.0+

How do I copy an object in Objective-C?

<NSCopying> Protocol and copyWithZone Method Implementation Now when executed, the above code creates a copy of the object referenced by account1 and assigns a pointer to the new object to variable account2.

How do I make a deep copy in Swift?

We can create a deep copy of the reference type using the copy() method. According to the documentation, copy() — Returns the object returned by copy(with:) . This is a convenience method for classes that adopt the NSCopying protocol.


2 Answers

Your base copyWithZone: method should look like this:

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

    // copy base members:
    // ...

    return base;
}

Your derived copyWithZone: methods should look like this:

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

    // copy derived members:
    // ...

    return derived;
}

Also make sure sure you are making deep copies of strong references and shallow copies of weak references. Thus to for example copy members of type NSString and NSArray (each one with strongly referenced members and one with weak) do:

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;

(Usually weak members are also assigned/retained and strong variables are copied.)

Take note that because of this you should not use initWithMyself: type methods to copy data.

like image 55
Marius Avatar answered Oct 13 '22 09:10

Marius


Ok first, your test code is bad because you set a saving number of 2001 in an 8 bit integer. Second, your code does not run because you're trying to call setSavingNumber:andOffer: on a BankAccount instead of an Saving object so it can't find the selector for this method at run time. Thanks David for pointing that out.

When implementing BankAccount::copyWithZone, you used the alloc-init and you returned the object which is fine. When implementing Savings::copyWithZone, you call super copyWithZone. What you get is an object of type BankAccount so you cannot use setSavingNumber:andOffer: on it. Since you used the alloc-init in the base class, you should also use the alloc-init and setMethods in the Savings class.

To avoid duplicating code, I'd recomment implementing an initWithBankAccount in BankAccount and the same in Savings.

Then in the copyWithZone, you'd have

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

and

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

Although you must make sure that in initWithSavings you call either

self = [super initWithBankAccount:savings];

or you call straight init and you copy the base member initialization.

Have a look at Implementing object copy from Memory management programming guide.

like image 34
Eric Fortin Avatar answered Oct 13 '22 09:10

Eric Fortin