Я собираюсь снова вызвать @bbum в надежде, что он получит сообщение, придет и исправит этот ответ .... Но я сделаю все возможное здесь.
В старом ABI,Вы не могли скрыть свои ивары.Компилятор поймает типы конфликтов, которые вы обсуждаете в любом случае, когда они имеют значение.Тем не менее, я обнаружил, что, вероятно, лучше просто избежать этой проблемы, используя другое соглашение об именах.Таким образом, когда вы обнаружите, что в вашем суперклассе уже есть _data
(как у меня), вам не нужно придумывать какое-то другое случайное имя или случайно получать доступ к личным данным суперкласса, когда вы не имели в видук.Несмотря на мою первоначальную неприязнь, нижнее подчеркивание Google выросло на меня с тех пор, как я использовал его в большом проекте.
Причина, по которой вы не могли скрыть свои ивары (и если бы вы сделали это каким-то образом, вы не получите столкновения именв любом случае) то, что ивары раньше были просто структурными смещениями.У Hampster Emporium есть хороший короткий пост , объясняющий это.Во время выполнения нет _window
, есть только смещение 20. (Опять же, это старый ABI, о котором я говорю).
Это не так для методов.Они могут столкнуться.Это плохо, когда это происходит.Вы не получите предупреждение.Меня действительно раздражает, что у Apple есть частные методы, которые не имеют подчеркивания.Я столкнулся с ними, и поведение не определено.Они защищены подчеркивание;они должны использовать это.(У NSMutableArray
был частный метод -pop
в категории, который был реализован в обратном направлении относительно того, как я реализовал мою категорию с тем же именем. Получающиеся ошибки в UINavigationController
были по меньшей мере интересными.)
Это отступление в сторону, с новым ABI, теперь возможно иметь «скрытые» ивары.Вы просто объявляете их как синтезированные свойства в расширении частного класса.Но благодаря магии нового ABI (хорошо, не магия, только указатели), ивары безопасны, даже если они сталкиваются. Но синтезированные методы не защищены от столкновения.Обратите внимание, что прямой доступ к ivar ниже дает вам ожидаемое поведение, но использование свойства дает удивительный результат.Я так и не понял, как разработчику лучше всего избегать или даже обнаруживать подобные ситуации.
EDIT Основываясь на моем обсуждении с @Bavarious, я переместил этот код вверсия clang, которая идет с Xcode 4 (большинство моих коробок все еще на Xcode 3).Он жалуется на всевозможные громкие ошибки, на которые вы надеетесь.В частности, вы получите «Свойство someIvar
уже реализовано».Так что это очень хорошо для использования @property
так, как вы хотите.
#import <Foundation/Foundation.h>
// SomeClass.h
@interface SomeClass : NSObject
@end
// SomeClass.m
@interface SomeClass ()
@property (copy) NSString *someIvar;
@end
@implementation SomeClass
@synthesize someIvar;
- (id)init {
self = [super init];
if (self) someIvar = @"SomeClass";
return self;
}
- (void)print
{
NSLog(@"Superclass=%@:%@", someIvar, [self someIvar]);
}
@end
// SubClass.h
@interface SubClass : SomeClass
{
NSString *someIvar;
}
@property (copy) NSString *someIvar;
@end
// SubClass.m
@implementation SubClass
@synthesize someIvar;
- (id)init {
self = [super init];
if (self) someIvar = @"SubClass";
return self;
}
- (void)print
{
[super print];
NSLog(@"Subclass=%@:%@", someIvar, [self someIvar]);
}
@end
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
SubClass *subclass = [[SubClass alloc] init];
[subclass print];
[pool drain];
return 0;
}
Superclass=SomeClass:SubClass <== Note the mismatch
Subclass=SubClass:SubClass