Domanda

Io sto usando un quadro che definisce e usi 'ClassA', una sottoclasse di NSObject. Vorrei aggiungere alcune variabili e funzionalità così naturalmente ho creato 'ClassB', una sottoclasse di 'ClasseA'

Ora il mio problema è questo. Molti dei metodi all'interno di questo quadro le istanze di 'ClassA' che vorrei lanciare al mio sottoclasse ritorno.

Ad esempio prendere questo metodo:

- (ClassA *)doSomethingCool:(int)howCool

Ora nel mio codice provo questo:

ClassB * objB;
objB = (ClassB *)doSomethingCool(10); 

NSLog(@"objB className = %@", [objB className]);

Questo funziona bene. Nessun compilazione o errori di runtime o niente. Ma ciò che è veramente strano per me è l'uscita:

>> "objB className = ClassA"

Il casting, ovviamente, non è riuscita. Non so cosa è successo a questo punto ... objB è tipizzata come 'ClassB', ma è className è 'ClassA' e non risponderà ai metodi di qualsiasi 'ClassB'.

Non so come questo sia possibile ... Qualcuno sa che cosa sto facendo male qui?

Ho trovato un post simile che è opposto esatto di quello che sto chiedendo qui

È stato utile?

Soluzione

Casting variabili oggetto in Objective-C è di solito un errore (ci sono alcuni casi in cui è giusto, ma mai per questo genere di cose). Si noti che non si sta lanciando un oggetto - si sta lanciando un puntatore per un oggetto. È quindi necessario un puntatore di tipo ClassB*, ma punta ancora alla stessa istanza di ClassA. La cosa indicò non è cambiato affatto.

Se davvero si vuole convertire le istanze di ClassA a ClassB, è necessario scrivere un metodo di costruzione ClassB che può creare un'istanza di ClassB da un ClassA. Se davvero bisogno di aggiungere variabili di istanza, questa potrebbe essere la scelta migliore.

Come ha detto Jason, però, è spesso una buona idea per cercare una categoria di prima.

Altri suggerimenti

Non si può semplicemente lanciare una classe super per la sua sottoclasse. In realtà non implementa le tue variabili / proprietà o metodi aggiunti. Non appena si tenta di messaggio con un metodo si definisce sul sottoclasse, che si sta per ottenere un'eccezione di runtime e l'applicazione sta per uscire. Si può solo lanciare in modo sicuro in una sola direzione: da di più specifico per più generale. Vale a dire, si può lanciare il nostro ClassB ad un ClasseA in modo sicuro, utilizzando solo i metodi e le proprietà di ClassA, ma non viceversa.

Pensare in questo modo: avete una macchina (la classe padre) e una FourDoorSedan (la sottoclasse). Ogni auto ha un motore e due porte. Ora, diciamo che si stanno ottenendo una macchina da qualche parte, e questo è davvero tutto quello che sai su di esso. Dite l'operatore, che auto è un FourDoorSedan, ma in realtà si scopre che non è. Così, quando l'operatore fa qualcosa di simile: openBackPassengerDoor, cosa succede? Ci sono solo due porte !! E 'lo stesso qui.

Se si desidera aggiungere un po 'di funzionalità per ClassA, controlla Objective-C Categorie, sono probabilmente quello che vuoi e sarà richiesto alcun casting. Leggere attentamente la documentazione, però, perché non sono senza i loro avvertimenti.

Se si desidera aggiungere un metodo per oggetti esistenti, creazione di sottoclassi non è il modo corretto. È possibile aggiungere il metodo alle classi esistenti (e le relative istanze) utilizzando una funzione di linguaggio chiamato categoria .

Esempio:

//"ClassA+doSomethingCool.h"
@interface ClassA (doSomethingCool)
- (ClassA *)doSomethingCool:(int)howCool;
@end


//"ClassA+doSomethingCool.m"
@implementation ClassA (doSomethingCool)
- (ClassA *)doSomethingCool:(int)howCool
{

}
@end

Casting non converte da un tipo di oggetto a un altro. Non si può costringere qualche libreria di cambiare tipo di oggetto e creare un altro tipo di oggetti a meno che non utilizza alcune modello di fabbrica.

Che cosa succede quando si chiama uno dei tuoi metodi delle sottoclassi sul oggetto restituito?

ClassB * objB;
objB = (ClassB *)doSomethingCool(10);
[objB subClassMethod];

Obj-C è abbastanza libera e perdere con i tipi, non c'è nemmeno bisogno di conoscere il tipo di prima mano, per esempio. è possibile modificare tutti i tuoi riferimenti ClassB a id. So che è più sicuro di sapere che avete il tipo previsto, ma se il codice è corretto non dovrebbe importare.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top