2010-08-06 6 views
5

por favor una mirada en siguiente código: ------- .hNSCopying y Sucesiones

@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 

Cuando ejecutar este código ::::::

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

no sé lo que está mal con el código por favor ayúdame. gracias por adelantado.

Gracias Deepak

+2

Formatee el código y formule una pregunta. ¿Cuál es el comportamiento actual, cuál sería el esperado? –

Respuesta

1

Ok en primer lugar, su código de prueba es malo porque se establece una serie de ahorro de 2001 en un entero de 8 bits. En segundo lugar, su código no se ejecuta porque está intentando llamar a setSavingNumber: andOffer: en una cuenta bancaria en lugar de un objeto de guardado, por lo que no puede encontrar el selector para este método en tiempo de ejecución. Gracias David por señalar eso.

Al implementar BankAccount :: copyWithZone, utilizó alloc-init y devolvió el objeto que está bien. Al implementar Savings :: copyWithZone, usted llama a super copyWithZone. Lo que obtienes es un objeto de tipo BankAccount, por lo que no puedes usar setSavingNumber: andOffer: en él. Como utilizó alloc-init en la clase base, también debe usar alloc-init y setMethods en la clase Savings.

Para evitar la duplicación de código, recomiendo implementar initWithBankAccount en BankAccount y lo mismo en Savings.

Luego, en el copyWithZone, tendría

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

y

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

Aunque debe asegurarse de que en initWithSavings llama a cualquiera

self = [super initWithBankAccount:savings]; 

o que llame directamente init y copia la inicialización del miembro base.

Eche un vistazo a Implementing object copy de la guía de programación de administración de memoria.

+0

A diferencia de C++ o C, la naturaleza dinámica de objetivo-c permitirá mensajes no controlados a un objeto, pero fallará en el tiempo de ejecución (a diferencia de la compilación, como usted menciona). Por favor, actualice la respuesta para reflejar esto. – David

+0

El problema de llamar 'initWithBankAccount:' en 'copyWithZone' de' BankAccount' es que no devolverá esos miembros como copias profundas. Esto puede o no causarle problemas más adelante. – Marius

+0

Por supuesto, esto está bien si todos los miembros son referencias débiles y no se necesitan copias. Pero tenga cuidado, por ejemplo, si quiere usar una clase como clave en un 'NSDictionary' o usarlos en' NSSet', luego cambiar los valores en los que se basa el pedido puede dar problemas/errores. – Marius

28

Su método de base copyWithZone: debería tener este aspecto:

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

    // copy base members: 
    // ... 

    return base; 
} 

Sus derivados copyWithZone: métodos deben tener este aspecto:

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

    // copy derived members: 
    // ... 

    return derived; 
} 

También asegúrese de que usted está haciendo copias en profundidad de referencias fuertes y poco profunda copias de referencias débiles. Por lo tanto a los Socios del ejemplo de copia de tipo NSString y NSArray (cada uno con los miembros fuertemente referenciados y uno con débil) hacer:

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; 

(. Por lo general, los miembros débiles también se asignan/retuvieron y las variables fuertes se copian)

Tenga en cuenta que, debido a esto, no debe utilizar los métodos de tipo initWithMyself: para copiar datos.

+0

copyWithZone no devuelve necesariamente una copia profunda. Echa un vistazo al patrón Prototipo. Utiliza el protocolo NSCopying junto con NSArchiver y NSUnarchiver para hacer que la copia profunda sea una tarea fácil. –

+2

+1 para '' self class] en la clase base allocWithZone. ¡Condenado sin eso! – Echelon

+1

En muchas preguntas de stackoverflow se explica NSCopying, pero de alguna manera se olvidaron de resaltar el uso de [self class]. –

Cuestiones relacionadas