Как вы объявляете экземпляр класса в Objective C?

#objective-c

#objective-c

Вопрос:

Давайте представим, что у меня есть класс Fraction. Итак, правильный способ создать его экземпляр — это:

 Fraction *myFraction;
or
myFraction = Fraction;
or
myFraction = [Fraction new];
  

или что-то еще?

В книге, которую я изучаю, правильный класс стоит первым, но мне это кажется неразумным. Почему мы должны создавать для него указатель? Почему бы нам не создать реальный экземпляр?

Это первое выражение означает — дайте мне указатель на новый экземпляр класса Fraction, не так ли?

Комментарии:

1. Обратите внимание, что вы можете форматировать строки как код , делая в них отступ в четыре пробела. Кнопка «{}» на панели инструментов редактора делает это за вас. Отредактируйте свой вопрос и попробуйте его. Нажмите на оранжевый знак вопроса на панели инструментов редактора для получения дополнительной информации и советов по форматированию.

Ответ №1:

Первый объявляет переменную с именем myFraction типа Fraction * , но ничего не создает и не инициализирует myFraction . Второе недопустимо. Третий создает новый класс Fraction и присваивает его ранее объявленной переменной с именем myFraction . Часто в Objective-C вы объявляете и инициализируете переменную в одном операторе:

 Fraction *myFraction = [[Fraction alloc] init];
  

Что касается того, использовать new или alloc с последующим init , это в значительной степени вопрос вкуса.

Переменные для хранения объектов являются указателями отчасти потому, что Objective-C унаследовал семантику C вызова по значению. Когда одна переменная присваивается другой (например, при передаче ее в функцию), значение будет скопировано. В лучшем случае это неэффективно для неизменяемых объектов. В худшем случае это приводит к некорректному поведению. Указатели — это способ обойти семантику вызова по значению и копирования при назначении: значение переменной с типом указателя — это просто указатель. Его можно скопировать, не касаясь целевого объекта. Стоимость этого заключается в том, что вам нужна какая-то форма управления памятью.

Ответ №2:

Было бы неплохо прочитать «Язык программирования C» Кернихана и Ричи, чтобы вы могли получить представление о том, как объявляются переменные.

В C и Obj-C и C существует два режима выделения: ручной и автоматический.

Целые числа, числа с плавающей запятой, символы и тому подобное Обычно объявляются автоматически. Они создаются при передаче объявления (т.Е. int i) и удаляются, когда область, в которой они были созданы, исчезает, т. е. когда вы выходите из блока, в котором они были объявлены. Они называются automatics. (их также можно объявить «статическими», но для целей этого обсуждения, касающегося распределения, это одно и то же)

Объекты слишком сложны для передачи функциям, поскольку параметры функции «передаются по значению», что означает, что параметр получает копию передаваемого значения вместо самой переменной. Потребовалось бы огромное количество времени, чтобы постоянно копировать весь объект.

По этой причине вы хотите просто сообщить различным функциям, где они могут найти объект. Вместо того, чтобы передавать копию объекта, вы передаете копию адреса объекта. Адрес сохраняется автоматически с типом указателя. (На самом деле это просто целое число, но его размер определяется оборудованием и ОС, поэтому он должен быть особого типа.)

Объявление Fraction *myFraction; означает «myFraction — это указатель, и, чтобы вы знали, позже он будет указывать на дробь».

Это автоматически выделит указатель, но не всю часть. Чтобы это произошло, вы должны вызвать alloc и init.

Основная причина, по которой у вас есть этот двухэтапный процесс, заключается в том, что, поскольку мы обычно хотим, чтобы объекты оставались на некоторое время, мы не хотим, чтобы система автоматически уничтожала их в конце функции. Нам нужно, чтобы они сохранялись. Мы создаем места для подвешивания объекта в наших функциях, но эти подвешивания исчезают, когда они не нужны. Мы не хотим, чтобы они забирали объект с собой.

В конечном счете, вы могли бы создавать объявления, подобные этому:

 Fraction *myFraction = [[Fraction alloc] initWithNumerator: 2 Denominator: 3];
  

в котором говорится: «Создайте мне дробь и установите ее равной 2/3, а затем поместите адрес этой дроби в ‘myFraction'».

Ответ №3:

Почему мы должны создавать для него указатель? Почему бы нам не создать реальный экземпляр?

В Objective-C каждый объект имеет тип указателя. Итак, вам нужно использовать либо new , либо alloc/init .

 Fraction *myFraction = [ Fraction new ] ;
  

или

 Fraction *myFraction = [ [Fraction alloc] init ] ;
  

И myFraction должен быть выпущен.

Это первое выражение означает — дайте мне указатель на новый экземпляр класса Fraction, не так ли?

Нет, вы просто объявляете указатель типа Fraction . И второе утверждение даже недопустимо.