Каковы некоторые из различных названий терминов и понятий в Objective C по сравнению с Java? - PullRequest
10 голосов
/ 02 августа 2009

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

Например:

  • ноль - ноль
  • это - я
  • карта - словарь (даже не совсем уверенный в этом)

То, что я ищу, - это сравнение или исправление, подобное тем, которые я перечислил. Не только элементы языка, но и понятия ...

Ответы [ 7 ]

12 голосов
/ 02 августа 2009

Вы правы насчет карты = словаря. Я добавлю:

  • @ public, @private, @protected (по умолчанию) предназначены только для переменных экземпляра (не для методов) и работают как модификаторы видимости в C ++ (т.е. вы объявляете их как заголовки разделов, а не перед каждой переменной).
  • Методы класса похожи на статические методы в Java
  • Существует только две структуры данных: NSDictionary и NSArray (в неизменяемых и изменяемых вариантах). Они высоко оптимизированы и хорошо работают в большинстве ситуаций. Для всего остального есть CHDataStructures
  • @ interface не работает как интерфейсы Java - он определяет переменные экземпляра и методы одного класса.
  • Вам нужны заголовочные файлы. С виноват в этом. Это в значительной степени отстой, так как поддержание вещей - это ненужная боль.
  • Нет понятия "пакет". Наиболее близким является фреймворк, но его не следует использовать в качестве пакетов Java (т. Е. Не создавать их просто для организации ваших классов).
  • Вместо «new Class ()» произнесите [[Class alloc] init]. Думайте о "alloc" как о новом операторе, а init как о конструкторе.
  • идентификаторы - это общие указатели объектов, например ссылки типа Object в Java.
  • Базовый класс - NSObject. Наследование от NSObject не является автоматическим и должно быть явно указано.
3 голосов
/ 02 августа 2009

Философский ответ о alloc / init.

init не является конструктором. Концептуально, «конструкция» не существует в Objective-C. В Java (и других языках с конструкторами) вызов конструктора вернет новое создание объекта, который готов к работе. Точного эквивалента в Objective-C нет. (Можно утверждать, что методы вспомогательного класса, такие как + array, + arrayWithObjects и т. Д., Являются технически конструкторами, поскольку они заключают в себе как распределение, так и инициализацию, но я бы сказал, что они все еще не являются конструкторами в том же смысле, что и конструкторы Java.)

Вместо этого у нас есть концепция выделения и инициализации, двух отдельных шагов, которые при выполнении вместе действуют так, как если бы они были «конструктором». Метод класса + alloc просто запрашивает кусок памяти соответствующего размера из системы. IIRC, он использует функцию calloc () для этого. Не гарантируется, что любое обнуление произойдет во время выполнения функции alloc. Это означает, что нам нужно выполнить инициализацию самостоятельно, что мы делаем немедленно , вызывая метод -init.

ОДНАКО, -init (и все производные) - не что иное, как обычные методы экземпляра. Вы можете отправлять им сообщения в любое время, чтобы «сбросить» экземпляр объекта в исходное инициализированное состояние (хотя при этом есть некоторые последствия для управления памятью, которые необходимо учитывать). Это также означает, что вы можете сделать что-то смешное, как это:

NSUInteger count = [[[NSArray alloc] autorelease] count];

Я не могу придумать вескую причину, почему вы хотели бы сделать это, но дело в том, что вы можете . Далее следует подчеркнуть, что init не является конструктором . В приведенном выше примере объект существует к моменту возврата метода + alloc. Тем не менее, он не может быть должным образом инициализирован, что означает, что целое число «без знака» может не быть нулевым. Возможно, но было бы неправильно полагаться на такое поведение (если, конечно, не задокументировано иное).

Одним из преимуществ разбиения конструкции на распределение и инициализацию является то, что мы можем в значительной степени контролировать то, что инициализируется. Например, в Java вы можете иметь только один конструктор для каждой сигнатуры метода. Другими словами, если у вас есть конструктор, который принимает один аргумент «Object», то это единственный конструктор, который может это сделать. Вы не можете создать другой конструктор, который также принимает один аргумент Object.

В Objective-C типы параметров не являются частью сигнатуры метода (известной как «селектор»), и поэтому я могу создать инициализатор следующим образом:

- (id) initWithAnObject:(id)anObject;

Однако я также могу создать другой инициализатор:

- (id) initWithADifferentObject:(id)anObject;

Я могу настроить их на выполнение совершенно разных инициализаций объекта, для которого они вызваны. Это невероятно полезно!

Еще один действительно полезный аспект разделения конструкции на распределение и инициализацию состоит в том, что вы можете связывать инициализаторы. AFAIK, вы не можете вызывать конструкторы из конструкторов в таких языках, как Java (ну, вы можете , но это не дает того же эффекта). В Objective-C, однако, вы можете сделать что-то вроде этого:

- (id) initWithCapacity:(NSUInteger)initialCapacity {
  if (self = [super init]) {
    [self setInitialCapacity:initialCapacity];
  }
  return self;
}

- (id) init {
  return [self initWithCapacity:0];
}

Теперь, когда вы выделяете / инициализируете объект, подобный этому, он будет «перенаправлять» и использовать инициализатор initWithCapacity, даже если вы вызвали init. (Вот как работает метод init NSArray) Это означает, что вы можете использовать условные инициализаторы. Например, ваш метод -init должен отправлять один инициализатор при определенных условиях, но использовать другой при других условиях.

Таким образом, модель Objective-C «выделить и инициализировать» гораздо более мощная, чем идея построения. Вы, как программист, имеете гораздо большую степень контроля над начальной фазой установки вашего объекта. Это действительно освобождающий сдвиг.

ps - init не является конструктором! ;)

3 голосов
/ 02 августа 2009

Другим концептуальным отличием является поведение при вызове методов (отправка сообщений) для нулевых объектов (до нуля).

Java

MyClass myObject = null;
myObject.doSomething(); <-- results in a NullPointerException

Obj-C

id myObject = nil;
[myObject doSomething]; <-- is valid

Здесь очень хороший вопрос об этом поведении.

2 голосов
/ 02 августа 2009

Предыдущие ответы охватывают большинство различий в "разговорниках", но есть несколько ключевых концептуальных различий, о которых стоит упомянуть ... (Обратите внимание, что я упоминаю только вопросы Objective-C, а не Какао.)

  • Существует плоское пространство имен для классов и одно для протоколов. Нет такой вещи как пакеты или иерархии пакетов. Все имена классов должны быть разными (и все имена протоколов должны быть разными) в приложении. Обычно это достигается с помощью ~ двухбуквенных префиксов.
  • Исключения зарезервированы для исключительного потока, почти всегда в результате ошибки программиста. Цели, для которых 95% + исключений Java лучше обслуживать, возвращая NSError , если необходимо.
  • Рассмотрите возможность использования категорий вместо одноразовых подклассов, но оба должны быть сделаны разумно и осторожно. (Категории делают иерархию наследования менее ограниченной, но влияют на все экземпляры класса. Они часто являются хорошим выбором, когда вы обычно делите подкласс, например, для элементов пользовательского интерфейса.) Часто (в обоих Objective-C и Java) лучшее решение - использовать вместо этого композицию.
  • Вы можете использовать динамическую печать практически везде, где хотите, просто имейте в виду, что это обоюдоострый меч. Это избавляет от необходимости большого количества приведений, но ошибки, которые будут обнаружены во время компиляции в Java, переносятся во время выполнения в Objective-C. Статическая типизация может использоваться где угодно и обеспечивает большую безопасность во время компиляции. (Java-разработчики часто рассматривают нестатическую типизацию как недостаток языка, но хорошо бы понять, какую гибкость это дает.)
  • Вы можете свободно смешивать функциональность C и библиотеки без JNI-оболочек. Но вы также получаете всю суету и ограничения прямой Си. Да, было бы замечательно, если бы мы могли покончить с необходимостью заголовочных файлов, но этого просто не произойдет для языков на основе Си. Жизнь не всегда справедлива. : -)
2 голосов
/ 02 августа 2009

с макушки головы:

  • Сериализация = Архивирование
  • Переменные экземпляра обычно доступны через свойства вместо явных методов доступа get / set. (В старые времена мы тоже писали аксессоры, но даже тогда они обычно имели вид foo / setFoo, а не getFoo / setFoo.)
  • Слушатель действия / кнопки / мыши / события примерно эквивалентен IBAction, хотя способ создания GUI в Какао весьма отличается от Java.
  • Вместо одного блока class определения классов определяются директивой @interface (для переменных экземпляра и объявлений методов) и директивой @implementation (для действительного кода метода).
2 голосов
/ 02 августа 2009

Интерфейс = Протокол

Поле = Переменная экземпляра ("ivar")

ArrayList = Array

вызов метода = отправить сообщение

Те, что вы перечислили, верны.

0 голосов
/ 02 августа 2009

Вместо использования итераторов для простого перечисления, которое вы обычно используете для классов, реализующих протокол FastEnumeration (интерфейс в Java), просто

для (элемент Class * в контейнере)

http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocFastEnumeration.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...