Вызов метода на неинициализированном объекте (нулевой указатель)

  1. Каково нормальное поведение в Objective C, если Вы называете метод на объекте (указатель), который является нолем (возможно, потому что кто-то забыл инициализировать его)? Разве это не должно генерировать некоторую ошибку (отказ сегментации, исключение нулевого указателя...)?
  2. Если это - нормальное поведение, есть ли способ изменить это поведение (путем конфигурирования компилятора) так, чтобы программа повысила некоторую ошибку / исключение во времени выполнения?

Для создания этого более ясным, что я говорю о вот, пример.

Наличие этого класса:

@interface Person : NSObject {

    NSString *name;

}

@property (nonatomic, retain) NSString *name;

- (void)sayHi;

@end

с этой реализацией:

@implementation Person

@synthesize name;

- (void)dealloc {
    [name release];
    [super dealloc];
}

- (void)sayHi {
    NSLog(@"Hello");
    NSLog(@"My name is %@.", name);
}

@end

Где-нибудь в программе я делаю это:

Person *person = nil;
//person = [[Person alloc] init]; // let's say I comment this line
person.name = @"Mike";            // shouldn't I get an error here?
[person sayHi];                   // and here
[person release];                 // and here
35
задан Cœur 4 September 2017 в 12:10
поделиться

2 ответа

Сообщение, отправленное объекту nil , совершенно приемлемо в Objective-C, оно рассматривается как бездействие. Невозможно пометить это как ошибку, потому что это не ошибка, на самом деле это может быть очень полезной функцией языка.

Из документов :

Отправка сообщений в ноль

В Objective-C допустимо отправлять сообщение в ноль - это просто не имеет никакого эффекта {{ 1}} во время выполнения. В Какао есть несколько шаблонов , которые используют этот факт . Значение, возвращаемое из сообщения в nil, также может быть допустимым:

  • Если метод возвращает объект, то сообщение, отправленное на nil , возвращает 0 ( nil ), например:

    Person * motherInLaw = [[aPerson супруга] мать];

    If aPouse супруга равно nil , тогда мать отправляется на nil , а метод возвращает nil .

  • Если метод возвращает любой тип указателя, любой целочисленный скаляр размера меньше или равного sizeof (void *) , a float , double , long double , или long long , затем сообщение отправлено на nil возвращает 0 .

  • Если метод возвращает структуру , как определено в руководстве по вызову функций Mac OS X ABI , которая должна быть возвращена в регистрах , то сообщение отправляется в {{ 1}} nil возвращает 0,0 для каждого поля в структуре данных.Другие типы данных struct не будут заполняться нулями .

  • Если метод возвращает что-либо, кроме вышеупомянутого значения types, возвращаемое значение сообщения , отправленного в nil, не определено.

63
ответ дан 27 November 2019 в 06:47
поделиться

Одна вещь, которую вы должны уяснить, - это то, что в Objective-C вы не вызываете метод для объекта, вы отправляете сообщение объекту. Среда выполнения найдет метод и вызовет его.

Начиная с первых версий Objective-C, сообщение о nil всегда было безопасным отказом от операции, возвращающим nil. От этого поведения зависит много кода.

6
ответ дан 27 November 2019 в 06:47
поделиться