Intro


До начала изучения Objective-C я программировал сначала на PHP, потом на Python и Ruby. Ruby мне понравился больше всего. Понравился своей простотой, лаконичностью, но в тоже время и мощностью. А около недели назад у меня наконец-таки получилось завести хакинтош на своем компьютере (сейчас у меня Macbook Early 2008 Black). Это оказался OS X Lion Golden Master. Я знал, что приложения для маков и айфонов пишут на Objective-C, даже пытался его выучить, но без OS X это было неприятно, что ли. Поставив Xcode 4.2 (я уже зарегистрированный iOS разработчик), написал несколько очень простых консольных приложений. И каждый раз когда я следовал какому-то туториалу, или просто пытался сам писать код, мне приходило в голову то, что, оказывается, Ruby и Objective-C имеют много общего (хотя это логично, так как оба языка были сделаны под влиянием Smalltalk), несмотря на то, что у этих двух языков совсем разные предназначения.
Итак, здесь я опишу некоторые вещи, которые помогут программистам на Ruby понять Objective-C, по большей части теоретические, без кода. Так же прошу прощения, если некоторые вещи будут объяснены не совсем по-сишному, я же пришел из мира Ruby.

1. Динамичность


Все мы знаем что Ruby — динамический язык программирования. Но как же Objective-C? Это же просто надстройка над C? Не совсем. Оказывается, Objective-C тоже в какой-то степени динамический язык. В нем многие вещи (например, отправка сообщения) и решения принимаются непосредственно во время запуска, а не во время компиляции.

2. Объектная модель


В Ruby, все — объект. Для Objective-C же это не всегда верно. Так как он является надстройкой над C, базовые типы данных (таки�� как char, float, double, int, struct) не являются объектами. Однако, фреймворк Foundation представляет функциональные обертки над ними, а так же такие, казалось бы, привычные вещи как строки, мутируемые массивы, хэши, и т.д.

3. Отправка сообщений


В Ruby когда мы вызываем метод объекта происходит неявная отправка сообщения:
object.send :method, args

то есть вызов метода преобразуется в отправку сообщения. В Objective-C происходит что-то похожее:
[object method];

Это именно посылка сообщения, а не вызов метода, поскольку если вызвать несуществующий метод, мы не получим никаких ошибок на этапе компиляции, только во время выполнения (что доказывает динамичность языка). Во время компиляции [object method] преобразуется в вызов C-шной функции objc_sendMsg(id object, SEL selector).

Как подсказывает farcaller в комментах:
clang3 на несуществующие методы умеет давать ошибки компиляции

Кстати, в терминологии языка C++ методы в Ruby и Objective-C являются виртуальными.

4. Нестрогая типизация


Каждый рубист знает, что с Ruby ему нет нужды заботится о типах переменных. Но не каждый знает, что в принципе c Objective-C — тоже. Если мы не знает тип объекта, в Objective-C можно просто указать тип объекта id, что значит — переменная может принимать значение любого типа. Ведь фактически, id — указатель на произвольный объект.
Однако для C-шных типов это не работает, только для объектов Objective-C. Хотя прибегать к типам C может потребоваться нечасто, ведь многие типы C имеют реализацию на Objective-C — NSNumber, NSString, NSArray, etc.

5. Объявления классов, создание объектов и свойства


В Ruby мы может просто определить в класс, в Objective-C мы вынуждены определить описание и саму реализацию класса. Обычно описание и реализация располагаются в разных файлах. В Ruby мы можем из любого метода определить любую переменную объекта, в Objective-C мы должны заранее определить все используемые внутри класса переменные.
В принципе, объекты создаются достаточно легко в обоих языках. В Ruby можно просто послать классу сообщение new
myObject = MyClass.new

в Objective-C же сначала необходимо выделить объекту память (alloc), а затем инициализировать его (init, initWith…)
MyClass * myObject = [[MyClass alloc] init];

Что бы получать доступ к instance-переменным мы должны определить два метода — геттер и сеттер. В Ruby мы можем просто написать attr_accessor :var, в Objective-C нам предстоит написать type * variable в разделе описания переменных класса, @property(retain) type * variable; после описания методов, и @synthesize variable; в реализации класса.

Небольшое отступление: поскольку Objective-C — надстройка над C, мы вынуждены заботится также и памяти. Компилятор LLVM поддерживает одну интересную фичу — Automatic Reference Counting, которая берет заботы об освобождении памяти на себя. Xcode версии 4.2 и выше использует компилятор от LLVM по-умолчанию, то есть о управлении памятью можно и не заботится, хотя, в принципе, для полного понимания языка было бы не плохо понять и такую, не совсем простую, тему как управление памятью.

6. Протоколы и миксины


В Ruby мы можем определять модули, а затем подмешивать их в классы, таким образом реализуется что-то вроде множественного наследования. В Objective-C конкретно такого нет. Зато в нем есть протоколы. Как говорит Wikipedia:

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

То есть, например, метод может принимать объекты, реализующий протокол Serializable и быть уверенным в том, что объект отвечает на сообщение serialize.

7. Категории и расширение классов


Если мы хотим расширить класс, в Ruby мы можем просто написать:

class String
  def my_super_method
    “New string”
  end
end


Таким образом мы добавим в класс метод my_super_method (хотя это и не единственный путь). В Objective-C мы можем сделать что-то похожее используя категории:

@interface NSString (HelloWorld)
+ (NSString *)helloWorld;
@end
@implementation NSString (HelloWorld)
+ (NSString *)helloWorld
{
  return @”Hello, World!”;
}
@end


Категории обычно сохраняются в файлы РасширяемыйКласс+НазваниеКатегории — NSString+HelloWorld.m и NSString+HelloWorld.h, а потом импортируются.

Вот лишь некоторые вещи, которые облегчили мне понимание Objective-C. Надеюсь, вам было интересно. Удачи!

Рекомендую обратить внимание на: