У меня возникли проблемы с пониманием следующего в книге Стивена Кочана «Программирование в Objective-C» - 4th Edition. Надеюсь, ты поможешь мне это понять.Инициализация объектов в Objective-C
В главе 10 на участке от «инициализации объектов», Стивен пишет:
Вы должны придерживаться следующих два стратегий при написании инициализаторов.
Возможно, вы хотите сделать что-то особенное, когда один из объектов вашего класса будет инициализирован. Например, это идеальное место для создания объектов, которые использует ваш класс, и ссылок через одну или несколько переменных экземпляра. Прекрасным примером этого может быть наш класс Rectangle; было бы разумно выделить начало XYPoint прямоугольника в методе init. Для этого нам просто нужно переопределить унаследованный метод init.
Там стандартная «шаблон», который используется для подмены инициализации, и это выглядит следующим образом:
- (id) init
{
self = [super init];
if (self) {
// initialisation code here.
}
return self;
}
Этот метод вызывает родительский Инициализатора первый. Выполнение инициализатора родителя гарантирует, что любые унаследованные переменные экземпляра будут правильно инициализированы.
Вы должны назначить результат выполнения метода инициализации родительского объекта самостоятельно, поскольку инициализатор имеет право изменить местоположение объекта в памяти (что означает, что его ссылка изменится).
Если инициатор родителя успешно завершен, возвращаемое значение будет не ноль, как проверено оператором if. Как указывает комментарий, внутри следующего блока вы можете разместить свой собственный код для своего объекта. Это часто связано с распределением и инициализацией переменных экземпляра, которые находятся в вашем классе.
ОК, так что до сих пор я понял, что пытается сказать Стивен Кочан, но я полностью озадачен следующей частью. Я надеюсь, что вы можете помочь.
Если класс содержит несколько инициализаторов, один из них должен быть назначенным инициализатором, и все остальные методы его инициализации должны использовать его. Как правило, это ваш самый сложный метод инициализации (обычно тот, который принимает большинство аргументов).
Итак, мой первый вопрос: почему есть все другие методы инициализации, если все они будут использовать один конкретный в этом случае «назначенный» инициализатор?
Стивен Кочан продолжает говорить:
Создание обозначенную Инициализатора централизует ваш основной код инициализации в одном методе. Любой подкласс класса может затем переопределить назначенный инициализатор, чтобы убедиться, что новые экземпляры правильно инициализированы.
Не могли бы вы привести пример этого? Я не совсем уверен, что понял, что он говорит.
Стивен продолжает:
На основе этого обсуждения, ваш метод инициализации initWith: более: для класса фракции может выглядеть следующим образом:
- (Fraction *) initWith:(int)n over:(int)d
{
self = [super init];
if (self) {
[self setTo: n over: d];
}
return self;
}
После инициализации супер (и его успех, как указано возвратом ненулевого значения), вы используете метод
setTo:over:
для установки числителя и знаменателя вашей фракции. Как и другие методы инициализации, вы должны вернуть инициализированный объект, который вы здесь делаете.Программа 10.1 проверяет ваш новый метод инициализации
initWith:over:
.
#import "Fraction.h"
int main (int argc, char *argv[])
{
@autoreleasepool {
Fraction *a, *b;
a = [[Fraction alloc] initWith: 1 over: 3];
b = [[Fraction alloc] initWith: 3 over: 7];
[a print];
[b print];
}
return 0;
}
Выход:
1/3
3/7
До сих пор я понял код. В следующей части я не понимаю:
Чтобы придерживаться правила, изложенного ранее о назначенном инициализаторе, вы также должны изменить init в своем классе фракций. Это особенно важно, если ваш класс может быть подклассом.
Вот что метод инициализации может выглядеть следующим образом:
- (id)init
{
return [self initWith:0 over:0];
}
Почему это важно, если мы хотим создать подкласс?
Стивен Кочан продолжает:
Когда программа начинает выполнение, он посылает вызов метода инициализации для всех классов. Если у вас есть класс и связанные подклассы, родительский класс сначала получает сообщение. Это сообщение отправляется только один раз для каждого класса, и оно гарантированно будет отправлено до отправки других сообщений в класс. Цель состоит в том, чтобы вы могли выполнить любую инициализацию класса в этой точке. Например, вы можете инициализировать некоторые статические переменные, связанные с этим классом в то время.
Я тоже не совсем понял эту последнюю часть. Надеюсь, вы сможете помочь.
Ответчик сделает это в ответах ниже; они не собираются отправлять вам по электронной почте. (Я удалил часть вашего вопроса, где вы упомянули об этом.) – CajunLuke
Есть ли проблемы с авторским правом (или проблемы с политикой SO) с цитированием этого большого текста и кода из опубликованной книги? Кажется, это намного больше, чем нужно задать вопрос; делает ли это обычные правила справедливого использования или что-то еще? – abarnert
@abarnert Я так не думаю, но IANAL. Я видел документы на уровне колледжа, которые цитируют больше, поэтому я думаю, что это в основном ОК, пока это явно цитируется, и есть какое-то обсуждение, чтобы пойти с ним. – CajunLuke