9.2 +load: выполнение кода до main
Этот раздел относится только к среде выполнения GNU Objective-C. Если вы используете другую среду выполнения, можете пропустить его.
Среда выполнения GNU Objective-C предоставляет способ выполнить код до того, как выполнение программы перейдёт к функции main. Код выполняется отдельно для каждого класса и категории с помощью специального метода класса +load.
Эта возможность очень полезна, если нужно инициализировать глобальные переменные, к которым программа может обращаться напрямую, не отправляя предварительно сообщение классу. Обычный способ инициализации глобальных переменных в методе +initialize может оказаться бесполезным, поскольку +initialize вызывается только при отправке первого сообщения объекту класса, а в некоторых случаях это может произойти слишком поздно.
Предположим, например, что у вас есть класс FileStream, в котором объявлены глобальные переменные Stdin, Stdout и Stderr, как показано ниже:
FileStream *Stdin = nil;
FileStream *Stdout = nil;
FileStream *Stderr = nil;
@implementation FileStream
+ (void)initialize
{
Stdin = [[FileStream new] initWithFd:0];
Stdout = [[FileStream new] initWithFd:1];
Stderr = [[FileStream new] initWithFd:2];
}
/* Other methods here */
@end
В этом примере инициализация Stdin, Stdout и Stderr в +initialize происходит слишком поздно. Программист может отправить сообщение одному из этих объектов до фактической инициализации переменных, в результате чего сообщения будут отправлены объекту nil. Метод +initialize, который непосредственно инициализирует глобальные переменные, вызывается только после отправки первого сообщения объекту класса. Для решения этой проблемы необходимо инициализировать эти переменные непосредственно перед переходом к main.
Правильное решение этой проблемы — использовать метод +load вместо +initialize:
@implementation FileStream
+ (void)load
{
Stdin = [[FileStream new] initWithFd:0];
Stdout = [[FileStream new] initWithFd:1];
Stderr = [[FileStream new] initWithFd:2];
}
/* Other methods here */
@end
Метод +load не переопределяется категориями. Если и класс, и его категория реализуют +load, вызываются оба метода. Это позволяет выполнить дополнительную инициализацию в категории.
Этот механизм не предназначен для замены +initialize. Если вы решите использовать его вместо +initialize, учитывайте его ограничения.
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-15.3.0/gcc/Executing-code-before-main.html