2010-11-03 7 views
3

Est-ce que quelqu'un aurait la gentillesse de confirmer que je comprends cela correctement. Ma réponse initiale à ceci était que le mutableArray quand assigné à un immutableArray deviendrait un immutableArray, cependant ce n'est pas le cas. Est-ce parce que le tableau initial est alloué en tant que mutableArray et que le tableau immutable est juste assigné pour pointer vers le même objet. Le compilateur donne un avertissement, mais le code s'exécute très bien à l'exécution.Affectation, mutable à un tableau immuable?

NSMutableArray *mArray = [NSMutableArray arrayWithObjects:@"Teddy", @"Dog", nil]; 
NSArray *iArray = mArray; 
[iArray addObject:@"Snoss"]; // Normally this would crash NSArray 

beaucoup apprécié

gary.

Répondre

4

Ne confondez pas l'objet physique que vous venez de créer , la façon dont vous êtes effectivley coulée dans votre code.

Dans ce cas, a créé physiquement un NSMutableArray.

Ensuite, vous l'avez converti en un NSArray - qui est totalement valide - par exemple, il existe de nombreux cas où une fonction peut vouloir un NSArray, et vous pouvez lui passer un NSArray, ou tout dérivé (comme un NSMutableArray). Le problème est que vous obtenez un avertissement de compilateur parce que vous essayez d'appeler addObject sur un objet que le compilateur considère comme étant simplement un NSArray parce que c'est son type physique.

Cela fait travail, parce qu'il fait est un NSMutableArray, et l'exécution répondrait à ce sélecteur.

C'est une mauvaise pratique de codage de le faire de cette façon, car NSArray ne répond pas réellement au sélecteur addObject. Par exemple, je pourrais créer une fonction, comme:

-(void) addIt:(NSArray)myThing { 
    [myThing addObject:@"New String"]; 
} 

Le compilateur vous donnera un avertissement disant que la « NSArray » ne répond pas au sélecteur « addObject ». Si vous lancez un NSMutableArray et que vous le transmettez à cette fonction, myThing, fonctionnera effectivement. Cependant, c'est une mauvaise pratique, car si vous passiez un NSArray, il tomberait en panne.

Résumé: Ne confondez pas ce que l'objet est vraiment par rapport à ce que vous faites le compilateur interprètent comme.

+0

Merci pour votre excellente réponse Brad, très apprécié. – fuzzygoat

2

Oui, vous avez raison. Vous devriez faire

NSArray *array = [NSArray arrayWithArray:mutableArray]; 

pour faire en sorte que personne ne peut changer le tableau

0

AFAIK, vous avez raison. NSMutableArray est une sous-classe de NSArray, donc vous pouvez assigner mArray à iArray ici sans problème.

Cependant, ce code n'est pas propre et vous devriez l'éviter.

1

Votre iArray fait référence à l'instance de NSMutableArray, c'est pourquoi il s'agit d'un NSMutableArray. Obj-c n'a pas de vérification stricte sur les types de classe, tous les objets sont de type 'id'. Vous pouvez écrire

NSNumber *iArray = mArray 

compilateur affichera un avertissement de mauvais casting (pas d'erreur). Mais ça va marcher. Ne jouez pas avec des pointeurs, il n'y a pas de transformations de type d'objet comme vous pouvez vous y attendre en C++

(il y a des opérateurs surchargeables pour lancer un objet dans une autre classe). Obj-c fonctionne avec des objets similaires aux scripts/langages interprétés.

Typage dynamique (objets seulement), réflexion, changement dynamique de méthodes d'instance de classes etc - flexibilité totale. Un mélange parfait de vitesse de C/C++ de bas niveau et de flexibilité de dynamisme.

Questions connexes