Perché alloc e init chiamato separatamente in Objective-C?
-
21-09-2019 - |
Domanda
Nota:. Sono relativamente nuovo per Objective-C e vengo da Java e PHP
Qualcuno potrebbe spiegarmi perché devo sempre prima assegnare e poi inizializzare un esempio?
Non potrebbe questo essere fatto nei metodi init in questo modo:
+ (MyClass*)init {
MyClass *instance = [MyClass alloc];
[instance setFoo:@"bla"];
return instance;
}
+ (MyClass*)initWithString:(NSString*)text {
MyClass *instance = [MyClass init];
[instance setFoo:text];
return instance;
}
...
E 'solo un relitto dei vecchi tempi C o c'è qualcosa che non sto vedendo?
So che questo non è un problema come ho potuto così sempre chiamare alloc e init, ma dal momento che è un po 'noioso mi piacerebbe almeno sapere perché lo sto facendo.
I sta piacendo l'espressività del linguaggio fino ad ora, ma questo è qualcosa che voglio comprendere appieno per pensare il modo in Objective-C.
Grazie!
Soluzione
+ nuovo finisce per l'invio di un messaggio di + alloc alla classe e un messaggio -init a tutto ciò che torna da + alloc.
La ragione per cui NeXT partì dalla convenzione di Stepstone di utilizzare il + nuovo messaggio (che era un'idea Smalltalk) è che nella fase iniziale, hanno incontrato situazioni in cui volevano essere in grado di inizializzare lo stesso oggetto più di una volta.
Altri suggerimenti
Poiché la creazione di un'istanza e inizializzare un'istanza sono due processi separati.
Si invia un messaggio alloc
alla classe per ottenere un'istanza non inizializzata. È quindi necessario inizializzare l'istanza, e si ha spesso diversi modi per farlo. Ad esempio:
myStr = [[NSString alloc] init]; //Empty string
myStr = [[NSString alloc] initWithFormat:@"%@.%@", parentKeyPath, key];
myStr = [[NSString alloc] initWithData:utf16data encoding:NSUnicodeStringEncoding error:&error];
myStr = [[NSString alloc] initWithContentsOfURL:URL encoding:NSUTF8StringEncoding error:&error];
Ognuno di questi inizializza la stringa in un modo completamente diverso. Come si inizializza la stringa dipende da ciò che si desidera inizializzare da.
Naturalmente, a nessuno piace la scrittura alloc
e quindi init
e poi autorelease
ogni volta, in modo di solito si hanno metodi di convenienza (per esempio, stringWithFormat:
) che fanno tutti e tre i passaggi per voi.
Modifica: Per ulteriori informazioni su questo argomento, tra cui intuizioni essenziali di commentatori, vedi il mio post sul blog “ Riunificazione ”.
Vedere NSZone
.
+alloc
è un taglio scorciatoia per +allocWithZone:
, che è un meccanismo Cocoa prevede ottimizzare allocazione di memoria.
Quindi, si ha la possibilità di fare qualcosa di simile a questo:
foo = [[NSString allocWithZone:MyZone] initWithString:@"Foo"];
foo2 = [foo copyWithZone:MyZone];
L'idea alla base di zone di memoria è che se si dispone di un gran numero di oggetti simili che sono frequentemente allocate e deallocato essa può più efficiente utilizzare una zona di memoria separata per tali oggetti.
Al fine di zonizzazione per essere efficace che ci si vuole avere +allocWithZone:
a disposizione di ogni sottoclasse NSObject, quindi è necessario separare l'allocazione e l'inizializzazione. È possibile creare e utilizzare tutti i collegamenti che si desidera, come +new
, ma sotto sotto è necessario un metodo -init
che inizializza un oggetto che è già stato assegnato.
"Separazione delle fasi di allocazione e inizializzazione di creazione dell'istanza fornisce molti vantaggi. È possibile utilizzare qualsiasi variazione del procedimento + classe alloc di assegnare un'istanza e quindi utilizzare qualsiasi inizializzatore disponibili con le nuove instance.This rende possibile creare i propri metodi di inizializzazione senza la necessità di fornire implementazioni alternative di tutti i metodi di assegnazione. Nuovi metodi di allocazione sono raramente creati perché i metodi esistenti si incontrano quasi ogni tipo di esigenza. Tuttavia, uno o più nuovi inizializzatori sono creati per quasi ogni classe. Grazie alla separazione delle fasi di assegnazione e inizializzazione, implementazioni inizializzazione avere a che fare con le variabili di nuovi casi e può completamente ignorare le questioni sur- arrotondamento allocation.The separazione semplifica il processo di scrittura initializers. Inoltre, cacao inizializzatori standard come -initWithCoder: lavorano con istanze indipendentemente dalla memoria modo per l'istanza è stata assegnata. Una conseguenza negativa della separazione di allocazione e inizializzazione è la necessità di essere a conoscenza di convenzioni come il designato initializer.You deve conoscere quali metodi inizializzatori designati e come creare e documentare nuovi initializers in sottoclassi. Nel lungo periodo, utilizzando inizializzatori designati semplifica lo sviluppo di software, ma v'è un argomento da effettuare quel modello di creazione theTwo-Stage si aggiunge alla curva di apprendimento precoce per gli sviluppatori di cacao. "
(c) Patterns Cacao Design by Erik M. Buck e Donald A. Yacktman
Non è necessario. È possibile utilizzare [MyClass new]
. Questo è simile al metodo init
ipotetica.
Fondamentalmente, Objective-C, che non hanno garbage collection inizialmente, separa il concetto di allocazione di memoria e l'inizializzazione di classe. Ecco perché ci sono due metodi distinti. Quando si chiama alloc
, si assegnano in modo esplicito la memoria.
La maggior parte delle classi hanno quello che stai chiedendo. Avete ottenuto risposte prima sul perché questo è come è e perché non sarebbe sempre desidera utilizzare questo tutto il tempo, ma se si legge la documentazione per le classi vedrete molti metodi di classe che agiscono in questo modo e sono spesso utilizzati.
Per NSString avete, per esempio:
+ (id)string // (Empty string)
+ (id)stringWithFormat:... // Formatted string (like you use)
+ (id)stringWithContentsOfURL:... // String populated with contents of URL
E così via. E si potrebbe quindi utilizzare questo come: NSString *myString = [NSString stringWithFormat:@"Hello %@\n", userName];
La maggior parte delle altre classi hanno questa, come NSArray:
+ (id)array
+ (id)arrayWithContentsOfFile:...
+ (id)arrayWithContentsOfURL:...
+ (id)arrayWithObjects:...
Hai solo bisogno di leggere la documentazione. :) E leggere le altre risposte sul perché non si desidera utilizzare questo troppo.
alloc : memoria viene assegnata / data all'oggetto riferimento. Ora di riferimento ha il possesso della memoria, ma non ha ancora fatto nulla. Questa memoria sia vuota (caso raro) o con alcuni dati anonimi.
alloc e init : memoria allocata viene pulito / svuotata. La memoria è iniziata da poco lo zero.
alloc e initwithdata ... :. Memoria allocata è iniziata con i dati desiderati rispettati per le proprietà della classe
Per esempio, quando si acquista una trama che si ottiene il possesso. Questo terreno è dato a voi come è, mattoni in rovina o vecchia casa può essere lì. Questo è alloc .
Quando si pulire il terreno e rimuovere tutta la sporcizia e rifiuti. Questo è alloc con init.
Quando si genera che in qualche casa di valore diventa più significativo per voi. Ed è alloc initwith ...