Question

Note:. Je suis relativement nouveau à Objective-C et de Java viens et PHP

Quelqu'un pourrait-il me expliquer pourquoi je dois toujours d'abord allouer et initialiser une instance?

pourrait pas être fait dans les méthodes d'initialisation comme ceci:

+ (MyClass*)init {
    MyClass *instance = [MyClass alloc];
    [instance setFoo:@"bla"];

    return instance;
}

+ (MyClass*)initWithString:(NSString*)text {
    MyClass *instance = [MyClass init];
    [instance setFoo:text];

    return instance;
}
...

Est-ce juste un relictuelle de l'ancien temps C ou est-il quelque chose que je ne vois pas?

Je sais que ce n'est pas un problème que je pourrais aussi bien toujours faire appel à alloc et init, mais comme il est un peu fastidieux, je voudrais au moins savoir pourquoi je le fais.

Je suis goût l'expressivité de la langue jusqu'à présent, mais c'est quelque chose que je veux comprendre afin de penser comme Objective-C.

Merci!

Était-ce utile?

La solution

+ nouveau finit par envoyer un message + alloc à la classe et un message -init à tout ce qui revient de + alloc.

La raison pour laquelle NeXT a quitté la convention de Stepstone d'utiliser le + nouveau message (ce qui était une idée Smalltalk) est que très tôt, ils ont rencontré des situations où ils voulaient pouvoir initialiser le même objet plus d'une fois.

Autres conseils

Parce que la création d'une instance et l'initialisation d'une instance sont deux tâches distinctes.

Vous envoyez un message alloc à la classe pour obtenir une instance non initialisée. Vous devez ensuite initialiser l'instance, et vous avez souvent plusieurs façons de le faire. Par exemple:

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

Chacun de ces initialise la chaîne d'une manière complètement différente. Comment vous initialisez la chaîne dépend de ce que vous voulez initialiser à partir.

Bien sûr, personne aime écrire alloc puis init puis autorelease chaque fois, vous avez généralement des méthodes pratiques (par exemple, stringWithFormat:) qui font les trois étapes pour vous.

Edit: Pour en savoir plus sur ce sujet, y compris des idées essentielles de commentateurs, voir mon blog « Réunification ».

Voir NSZone.

+alloc est une coupe de raccourci pour +allocWithZone:, qui est un mécanisme de cacao fournit pour optimiser l'allocation de mémoire.

Vous avez la possibilité de faire quelque chose comme ceci:

foo = [[NSString allocWithZone:MyZone] initWithString:@"Foo"];
foo2 = [foo copyWithZone:MyZone];

L'idée derrière les zones de mémoire est que si vous avez un grand nombre d'objets similaires qui sont souvent affecter et de désaffecter il peut plus efficace d'utiliser une zone de mémoire séparée pour ces objets.

Pour le zonage soit efficace, vous voudriez avoir +allocWithZone: à la disposition de chaque sous-classe NSObject, il faut donc séparer l'allocation et l'initialisation. Vous pouvez créer et utiliser tous les raccourcis que vous voulez, comme +new, mais en dessous tout ce que vous besoin d'une méthode -init qui initialise un objet qui a déjà été attribué.

"Répartir l'allocation et les étapes d'initialisation de la création d'instance fournit de nombreux avantages. Il est possible d'utiliser une variante de la méthode de classe + alloc d'allouer une instance et utiliser ensuite toute initialiseur disponible avec les nouveaux instance.This rend possible de créer vos propres méthodes d'initialisation sans avoir besoin de fournir des implémentations alternatives de toutes les méthodes d'allocation. Les nouvelles méthodes d'allocation sont rarement créés parce que les méthodes existantes répondent presque tous les besoins. Cependant, un ou plusieurs nouveaux initialiseurs sont créés pour presque toutes les classes. En raison de la séparation des étapes d'allocation et l'initialisation, les implémentations de initialiseur ont seulement pour traiter les variables de nouvelles instances et peuvent ignorer complètement les problèmes d'arrondi sur- allocation.The séparation simplifie le processus d'écriture des initialisations. En outre, initializers standard Cocoa comme -initWithCoder: travailler avec les instances quelle que soit la mémoire de façon pour l'instance a été alloué. Une conséquence négative de la séparation de l'allocation et l'initialisation est la nécessité d'être au courant des conventions telles que le désigné initializer.You doivent savoir quelles méthodes sont désignées initializers et comment créer et documenter de nouvelles initializers dans les classes sous. À long terme, l'utilisation initialiseurs désignés simplifie le développement de logiciels, mais il y a un argument à faire ce modèle theTwo-étape Création ajoute à la courbe d'apprentissage pour les développeurs Cocoa. "


(c) Modèles de conception de cacao par Erik M. Buck et Donald A. Yacktman

Vous n'avez pas. Vous pouvez utiliser [MyClass new]. Ceci est similaire à votre méthode de init hypothétique.

En fait, Objective-C, qui n'a pas eu la collecte des ordures au départ, sépare le concept d'allocation de mémoire et l'initialisation de la classe. Voilà pourquoi il existe deux méthodes distinctes. Lorsque vous appelez alloc, vous allouez explicitement la mémoire.

La plupart des classes ont ce que vous demandez. Vous avez obtenu des réponses avant pourquoi c'est comme il est et pourquoi vous ne voudriez pas toujours d'utiliser tout le temps, mais si vous lisez la documentation des classes, vous verrez de nombreuses méthodes de classe qui agissent de cette façon et ils sont souvent utilisés.

Pour NSString vous avez, par exemple:

+ (id)string  // (Empty string)
+ (id)stringWithFormat:...  // Formatted string (like you use)
+ (id)stringWithContentsOfURL:... // String populated with contents of URL

Et ainsi de suite. Et vous pouvez ensuite utiliser cela comme: NSString *myString = [NSString stringWithFormat:@"Hello %@\n", userName];

La plupart des autres classes ont cela, comme NSArray:

+ (id)array
+ (id)arrayWithContentsOfFile:...
+ (id)arrayWithContentsOfURL:...
+ (id)arrayWithObjects:...

Il vous suffit de lire la documentation. :) Et lire les autres réponses sur la raison pour laquelle vous ne souhaitez pas utiliser ce trop.

alloc : La mémoire est allouée / donnée à la référence d'objet. Maintenant référence a la possession de la mémoire, mais n'a pas encore fait quoi que ce soit. Cette mémoire soit vide (cas le plus rare) ou avec des données anonymes.

alloc et init : mémoire allouée est nettoyée / vidé. La mémoire est initiée par bit zéro.

alloc et initwithdata ... :. Mémoire allouée est initié avec des données désirées à respecter propriétés de la classe

Par exemple, lorsque vous achetez un terrain que vous obtenez la possession. Cette parcelle est donnée à vous comme il est, briques ruinées ou vieille maison peut être là. Ceci est alloc .

Lorsque vous nettoyez votre parcelle et enlever toute la saleté et de la litière. Ceci est alloc init.

Lorsque vous construisez que dans une maison précieuse, il devient plus significatif pour vous. Et il est alloc initwith ...

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top