Как стать автором
Обновить

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

Большая статья, плюс за труд, но смущают некоторые моменты, например:

NSObject *object = [NSObject alloc];

выделил для него такой адрес в памяти

0x000000000

Так происходит потому что при инициализации, исполняемая среда, всем объектам задаёт значение «nil»...


Возможно, вы имели в виду, что alloc инициализирует нулями все (кроме isa) переменные (члены) создаваемого экземляра?

Иначе кто-то может подумать, что alloc возвращает нулевой адрес.

Еще фрагмент:

NSObject *object = [NSObject alloc];
[object init];


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


Скорее, здесь вероятность использования далее в программе неинициалированного объекта.

В общем, было бы неплохо уточнить формулировки, у нас сейчас люди начинают изучение, боюсь, мне придется делать им дополнительные разъяснения после вашей статьи.
Уточнил
Скорее, здесь вероятность использования далее в программе неинициалированного объекта.

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

Смотрите:

NSObject *object = [NSObject alloc];
[object init];

[object doSomeAction]; // использование неинициализированного объекта

Какой противный синтаксис :(
Да, когда-то увидев это, я пришёл к твёрдому выводу, что под Мак писать не буду. %)
Под мак можно без проблем писать на С\С++ ;)
НЛО прилетело и опубликовало эту надпись здесь
Меня тоже синтаксис пугает. Но там не только это пугает, а то что лишний пробел в коде может привести к его невыполнению. Под мак можно спокойно писать программы на python или ruby. А для ios сойдет вот это или вот это
НЛО прилетело и опубликовало эту надпись здесь
тоже интересно.
* object
НЛО прилетело и опубликовало эту надпись здесь
NSObject *object = [NSObject alloc];
NSObject * object = [NSObject alloc];

Две строки выше абсолютно одинаковы для компилятора, если вы это имеете в виду. Хотя, если вы пишете на C++, вам это должно быть известно.

Поясните, что вы имели в виду?
Два года назад xcode выдавал ошибку, когда я ставил пробел после звездочки. Я не сразу понял даже, где ошибка. А когда понял, психанул, потому что последний раз я сталкивался с этим в Turbo Pascal и тогда положил немало нервов.
Если в новом xcode это поправили, то это замечательные новости!
В новом xcode это не поправили, потому что этого никогда там не было.

Может, он и выдавал вам ошибку, но, боюсь, вы неправильно определили ее причину.

Тогда использовался gcc. Этот компилятор мог справиться с лишним пробелом и раньше 2010 года.
А почему, когда я пробел убрал, у меня все запустилось? Это была прога простейшего калькулятора. Как я мог неправильно определить причину в таком смешном деле?
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
Ок, я встречался с интересным случаем в другом языке. Когда в программе была не критическая ошибка (о которой не сообщалось) и компилятор исполнял ее. При появлении критической ошибки, компилятор указывал на не критическую, а после ее исправления, показывал критическую. Но там был компилятор кривоватый, это я уже потом вычитал.
Не выдавал, даже когда еще назывался Project Builder :)
И как вы тогда объясните, что я тут про этого говорю?
Никак, зачем мне объяснять чей-то бред?
Всю жизнь пишу астерискус отдельно от имени, прямо сейчас делаю это в тигре (xcode 2.5) :)
Нет проблем, всей толпой меня тут убедили, что проблема во мне. Возвращаюсь к изучению ObjC. Но я вас тут всех запомнил :) Будут проблемы, буду спрашивать в личке. Не против?
спрашивайте :) буду рад проконсультировать ;)
Не против :)
Хватит уже обсирать другие языки программирования :) никакой он не противный :)
Просто каждому — свое :) у всех разные вкусы и предпочтения
Пусть не пишут, нам больше достанется. :-)
Как вариант, можно писать на Mono :)
Objective-C как первый язык программирования

Сочувствую. Сострадаю.
Objective-C как первый язык программирования — отличный выбор! Через 2-3 месяца изучения уже появится шанс устроиться джуниором. Сочувтсвовать надо начинающим С++ программистам!
Начинать надо не с Objective-C и не с С++, а с кристально чистого С.
Не возражаю, но если задаться целью как можно быстрее войти в профессию, то сильно углубляться в С не стоит. Освоить синтаксис, немного порешать алгоритмических задачек, и переходить к Objective-C и Cocoa.
И остаться на всю жизнь посредственным программистом?
Не углубляться в С и заниматься программированием — это как не учиться водить и участвовать в гонках. Понимание С ведет к пониманию того, как работает процессор, память и т.д. Знание того, как работает система позволяет писать быстрый и качественный код. А так же простой, как дверь — без куч ненужных интерфейсов, фабрик и прочего.
Пример: у вас есть выбор — использовать лист или массив, скорость вставки нас не волнует — нам надо будет линейно искать элементы в одной из этих структур. Сложность поиска в обеих структурах — О(n). Аргументировано сделайте выбор структуры? Я задавал эту простую задачку «программистам» которые начинали со всяких ява\C# и они ничего не знают о памяти. Отвечали, что выберут массив, на вопрос почему ничего не могли ответить, видимо, потому что привычнее и эту структуру они выучили первой. Когда я акцентировал внимание на том, что сложность поиска в обеих структурах одинаковая, т.е. по сути ж никакой разницы в выборе нет. Они терялись.
Ну и ответ, почему же я выберу массив — все элементы расположены друг за другом, это дружественно к кэшу. Я запрашиваю один элемент, а с памяти мне придут вместе с ним несколько других, расположенных за ним. В случае с листом, в зависимости от ужасности аллокатора памяти, я буду получать постоянные кэш миссы при доступе к следующему элементу массива. И на практике скорость поиска в массиве будет значительно быстрее — опять же, в зависимости от системы. На старых тачках с ддр1-2 латентность памяти ниже, чем у ддр3, следовательно кэш миссы будут «дешевле», а значения следующего элемента придет быстрее.
Опять же, в зависимости от ужасности аллокатора памяти, реальный объем памяти выделенный под элементы листа может в разы превосходить по объему память для массива. Будет большая фрагментация памяти, что в больших системах приведет к понижению производительности всей системы в целом.
Можно сидеть дома и читать книжки по С, а можно пойти работать по специальности и получать ЗП. Я рекомендую второй вариант.
PS: Приведенные в вашем примере знания, могут устареть раньше чем понадобятся. Начинающие программисты на ObjC тоже выберут массив, структуры данных «лист» в чистом виде в этом языке просто нет. А продвинутые программисты, если вообще будут заморачиваться на оптимизации, то выберут векторную обработку больших объемов данных.
Можно сидеть дома и читать книжки по С, а можно пойти работать по специальности и получать ЗП. Я рекомендую второй вариант.

Можно сидеть дома и читать книжки по С, а можно пойти писать говнокод.
Для разработчика лучше получать опыт и делать ошибки, в которые более зрелые коллеги натыкают носом, и разжуют что и как. А работодателя тоже жалеть не надо, для него это осознанный выбор цена/качество.
И вообще, что есть «говнокод»? Наверно вы имеете ввиду часть какого-то говнопроцесса, при котором говнокодеры делают говнокод в говнопректе для говноклиента за говнобаксы. А виноватым во всем этом сделаем джуниора, который недочитал книжку по С!
Для разработчика лучше получать опыт и делать ошибки, в которые более зрелые коллеги натыкают носом, и разжуют что и как.

Именно для разработчика, а не для недоросли, которая не понимает, что происходит вообще. Такие люди тянут проект вниз, требуя (если вообще что-то пытаются понять) от коллег неоправданно много времени на растолковывание очевидных вещей и производя на свет говнокод, который ни в каком виде не годится ни для использования, ни для поддержки. Я жалею не работодателя, а разработчиков, обреченных нянчиться с такими кадрами, поскольку мне самому доводилось с этим иметь дело.

Джуниор — это программист, знающий все свои инструменты и языки, но не обладающий достаточным опытом для самостоятельного принятия проектных или прочих сложных решений. Человек же, не владеющий фундаментальными знаниями, — это не джуниор, это быдлокодер.
То есть Вы отрицаете само существование джуниоров в том виде, в котором они сейчас присутствуют на рынке труда?
И сами Вы небось даже не были джуниором? Родились с клавиатурой, программировали с детского садика, и даже в садике Вашему коду завидовал Макконнел.
Если бы планка вхождения была на таком уровне — программировали бы только три человека: Керниган, Ритчи и Вы.
Таким джуниором, как описываете Вы, я не был. Я хорошо учился в университете. Огромная доля джуниоров, с которыми мне приходилось работать, такими не были тоже. А полуграмотные обезьянки в большинстве случаев такими же и обезьянками и остаются после трудоустройства. Есть, конечно, талантливые ребята, но таким прочитать K&R обычно не составляет труда.
Охохох, до недавнего времени в Obj-C не было ARC и с памятью работа была почти ручной :) Так что без понимания работы с памятью было никуда.
А про то, как работают процессоры и глубже человек должен выучить в университете.
По-моему, тем, кто начинает с Java или Objective-C, гораздо легче даются основы языков уровня пониже. Да и понимание приходит быстрее.
Это же абстракция в чистом виде :)
Люди сначала учат, что 2 * 2 = 4, и только потом учат, почему так :)
Я не предлагаю учить ассемблер. Я говорю о С, возьмите любую книгу по С для новичков — там сначала тоже все просто, как 2 * 2
Ну и я не говорю, что С учить не надо :) просто говорю, что начал с Objective-C и, по собственному опыту, считаю, что с него начинать удобно :)
Листы-то ведь бывают не только связные. И в C# и в Java в качестве стандартной реализации листа используют array list, в котором элементы хранятся в массиве и проблем с разбросом по памяти во время поиска не имеют.
Это был пример, хоть и плохой.
мой первый язык Objective-C. Я ни о чем не жалею. Что я делаю не так?
Какие языки знаете? На каких активно программируете?
знаю Java, Objective-C :)
на обоих активно программирую :) Java — для университета, Objective-C — свои проекты :)
«Седельный тягач как первая машина. Учимся на практике.»

Кстати, язык понятный. Если знаешь что угодно из C-семейства, то необычным кажется только синтаксис, но не сам смысл. Можно привыкнуть, короче.
А вот мы в университете понимали что такое ООП на Smalltalk и для меня obj-c теперь любимый и лучший :)
Спасибо за статью. Я начинал с делфи, сейчас изучаю Objective-C. Хочу сказать что синтаксис с кучей слов сначала был, ммм, странным да, но потом привыкаешь и оказалось что это очень удобно. Но как первый ЯП я бы его не выбрал :) Считаю, что сначала лучше выучить алгоритмы и ООП на чем-нибудь другом. Хотя, может я и не прав…
сейчас достаточно часто встречаю ссылки что в качестве первого языка лучше использовать CoffeeScript и Lua — из-за большого количества синтаксического сахара, и распространенности (CoffeeScript — Ruby и Web) и (Lua — игровая индустрия)
Какой-то излишне путанный способ объяснять принципы ООП. Создаётся впечатление, что автор сам еще до конца не понял что к чему.
В данном случае «себе» — это классу «Primus»

Точно классу а не экземпляру класса?

Советую автору пописать чуть-чуть объектных моделей на Java — сразу всё станет очень просто и понятно.
TL;DR: Статья очень плохая, потому что внутри мешанина всех и вся. Кроме того,
хотя знание С было заявлено как не нужное, а дальше идет куча ляпов из-за не
знания С.

Автору – вы учитесь и на правильном пути. копните глубже в фундаментальные вещи,
это позволит вам лучше понять природу вещей. Ничего в программировании не
происходит «автоматически». Докапывайтесь до причин, это весьма полезные знания.

> Начало: метод класса и метод экземпляра

Интересное «начало», учитывая какие темы рассматриваются дальше.

> Класс для Objective-C, часто можно интерпретировать как объект и наоборот

Очень сложное к пониманию предложение.

> есть классы, которые нельзя назвать объектами. Они называются «протоколы»

Протокол нельзя «создать», потому в данном случае сравнение не корректно.

> Различие состоит в том, что «протокол» не может иметь подкласс или дочерний
> объект

То что вы не сталкивались с иерархией в протоколах, не значит, чо ее нет ;-)

И да, «дочернего объекта» у протокола может и не быть. Но можно «привести» тип
объекта к протоколу.

> Вот те методы, которые со знаком "-" мы активно применяем как в отношении
> объектов — экземпляров класса, так и отношении самого класса

Нет, методы с "-" нельзя применять к классу.

> Любой другой объект в Objective-C по определению — потомок NSObject

Нет. И да, я понимаю что вы пытаетесь написать статью для новичков, но новички
с заведомо ложными убеждениями – это большая проблема для нас в будущем.

> NSResponder’а тоже могут быть дочерние объекты

Наверно дочерние классы?

> выделяет для него место в ОЗУ

Выделяет место в ОЗУ как раз таки +alloc, а не -init.

> выделил для него такой адрес в памяти
> 0x000000000

У вас только что зафейлился malloc, сопротивление бесполезно. В качестве примера
указателя лучше использовать что-то с живыми цифрами.

> Вы будете удивлены тем, чему равняется Ваше «i»

Не буду удивлен. А почему? А потому что я знаю как работает стек. Знать про стек
в языках основанных на С – полезно. Иногда полезнее, чем уметь создавать
сабклассы табличек с кнопочками в ячейках.

> Также будет создан экземпляр объекта «isa»

Нет. isa – это указатель на структуру класса. Она уже создана рантаймом (еще во
время линковки).

> То есть теоретически объект уже есть после применения метода «alloc»

Он практически «есть». Но «существовать» – не значит «быть готовым к
использованию».

> потому что он вроде как есть, но в принципе он равен «nil»

Он не равен nil, я вам точно говорю.

> В файле «Primus.h» объявлены методы:

Не совсем понятно куда пропали ± ил примера. Он не нагляден.

> В отличие от некоторых других языков программирования в Objective-C методы не
> вызываются, а посылаются объектам

Это предложение, в контексте параграфа, лишено смысла, так как не объясняет, в
чем, собственно, разница.

> Скажем это «слабый» тип объекта

Не стоит так говорить, потому что будет сложно ответить на вопрос, что такое
"__weak id".

> Что такое «void»?

void – это тип данных, который фактически обозначает «тут ничего нет». Нельзя
объявить переменную «void» – потому что в ней ничего не будет. Но можно объявить
указатель «void *» – потому что переменная хранит адрес, а вот адрес чего, ее
уже как-то не так сильно волнует. Фактически проблема будет только если этот
указатель разименовать.

Методы возвращают «void» когда они, собственно, не возвращают ничего. В паскале
для них есть отдельный термин – процедура, но обычно ЯП на такое не
размениваются.

> Но не в конце

return можно писать и в конце (хотя в этом и мало смысла, да). Но метод, который
возвращает void не может содержвать в себе код «return XXX;», потому что все что
программист напишет в XXX – осязаемо и имеет смысл.

> Что такое «self»?

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

А еще стоило бы сказать про канонические аргументы self и _cmd в любом IMP и все
стало бы проще.

> if (!myPrimus){

в контексте инициализатора в Objective-C эта проверка лишена смысла. Проверяют,
обычно, что [super init] не вернул nil (эта ситуация на самом деле крайне редка
и сейчас больше дань традиции). В вашем коде проверяется что +alloc не вернул
nil, но если он вернул nil, у вас есть намного более существенные проблемы, о
которых надо волноваться в данный момент.

> Для того, чтобы понять можно ли написать «self» или нельзя

В лобом методе можно писать self.

> casserolAndPan:(NSArray)pan

NSArray * же.

> Если есть переменная, например «variable», то задать ей нужное значение можно
> через префикс «set»

Задать значение переменной можно через оператор "->"

self->temperature = 500;

Но опять же, для этого надо знать немного С, что бы понимать указатели и что
происходит.

> Это можно производить не только через свойства, но и через доступ к ним по
> принципу ключ-значение

KVC в статье, где рассказывается про базовое ООП, как-то несколько лишнее.

> Понятие «runtime» можно охарактеризовать

Нет. Runtime – это дословно «среда исполнения». Это тот код, который выполняет
все то, что в вашем коде остается «за кадром». Этот код, фактически, выполняет
все те «магические» штуки. И не важно, на чем он написан. В случае с
Objective-C, там есть и C++, а у C++ есть свой рантайм.

> [myPrimus initWithGas:gelium temperature:nil];

второй аргумент – это NSInteger, пишите типы корректно.

> Единственная его переменная

NSObject – он не такой простой.

> Затем присвоить ему „nil“, для того чтобы он не взял случайный адрес в памяти. Конструкция
> static dispatch_once_t predicate;

Значит объекту nil надо присваивать, а предикату – нет? А как он тогда работает?
И снова надо копать в С, и в static, и в то, что статические переменные при
запуске приложения будут обнулены.

> [super allocWithZone:nil]

Ну зачем вы еще +allocWithZone: вытащили, +alloc мало?

> опять же присваивая ему «nil» в качестве адреса размещения

Откуда у вас эти идеи берутся? Наверно, от того что вы продолжаете игнорировать
наследие С? PAGEZERO например, сегмент, который применяется для первой страницы
в виртуальном адресном пространстве что бы ловить «бажные» нулевые указатели.

> Методы протоколов Вы не посылаете своему объекту

Что мешает вам это делать? Это вообще нормальное использование протоколов.

> Внутри любого метода протокола может быть любой метод класса

О чем это?

> То есть, метод протокола — это контейнер, в котором находятся любые другие
> методы, собственно как и любой реализуемый Вами метод

Я даже не могу прокомментировать, просто не понятно, что происходит.

> К примеру, нужно сделать так, чтобы Ваша формочка делала что-то, при
> определённых условиях

Формочка – это наследие делфи? Раз уж было упомянуто MVC, то и остальную
терминологию стоило бы причесать.
Ох. Меня тоже все это смущает. Очень неточные формулировки и странные (иногда) выводы.
> return можно писать и в конце (хотя в этом и мало смысла, да). Но метод, который
> возвращает void не может содержвать в себе код «return XXX;», потому что все что
> программист напишет в XXX – осязаемо и имеет смысл.
void foo() { return void(); }
:)
Замечания конечно вполне уместные. Но хотел бы я посмотреть на Ваши формулировки озвученных в статье вопросов, если бы вы от силы 2 месяца программировали. А до этого были сисадмином — эникейщиком.
Я повторяю еще раз – плюс за старания. Минус – за содержимое. Старайтесь еще!
НЛО прилетело и опубликовало эту надпись здесь
Но хотел бы я посмотреть на Ваши формулировки озвученных в статье вопросов, если бы вы от силы 2 месяца программировали.

И в итоге описание получается в духе

Это может еще больше запутать начинающего программиста.
Но писать заведомо неправильные вещи тоже не очень хорошо
Статью не читал, но осуждаю.

> Objective-C как первый язык программирования

Вы с ума сошли начинать образование будущего (хотелось бы верить) профессионала с ООП.
ООП-то как раз там самое каноничное ;)
Я с Java начал (который писал народ ушедший с Objective-C кстати) и что? Потом тот же C и C++ (Objective-C уже два года как знаю, пишу игру) выучил и вполне нормально живу и дышу. Хотите поспорить давайте в личку.
Нетипобезопасный язык программирования, приучающий ложить на типизацию большой прибор как первый язык? Отказать.
Этот язык не приучает класть на типизацию и опасен не более, чем C или C++ при работе с указателями.
А как же волшебный тип id? В C++ хотя бы кастить надо к нужному типу, чтобы метод вызвать, причем кастинг проверяемый (если dynamic_cast).

Ну и отсутствие какой-либо формы параметрического полиморфизма делает все коллекции нетипобезопасными.
Объясню свое недовольство по поводу id. Часто вижу такое, что разработчики делают property/ivar/аргумент типа id с мыслью «а, потом придумаю, что сюда передавать, все равно ведь можно вызвать любой метод будет и проверить класс через isKindOfClass». Нафига думать и проектировать архитектуру, точно зная что куда передается, действительно, ведь есть же id!
НЛО прилетело и опубликовало эту надпись здесь
ну, наличие duck typing очень к этому располагает
НЛО прилетело и опубликовало эту надпись здесь
good for you!
Наличие id не означает, что Objective-C поощряет его использовать вместо конкретных типов.
Отсутствие типобезопасных коллекций тоже не поощряет пихание разнородных элементов в NSArray, однако лишает разработчика ряда compile time проверок.
При использовании id разработчик лишается compile time проверок, при использовании конкретных типов — не лишается. Так что же рациональнее использовать разработчику?
В общем, очень весело получилось.
Зашел в тему, сказал, что не стоит унижать другие языки программирования, что у каждого свой вкус; высказал свое мнение, не навязывая его никому из присутствующих.
Карма поползла вниз, комментарии заминусованы.
Хабр в собственном соку…
Не бойтесь, унижатели языков вроде меня (это мой комментарий сверху самый заплюсованный в топике) — тоже по карме словили. :)
Если Вы, никогда не программировали, то книга Кернигана и Ритчи (в любом издании), Вам явно будет не по силам.

Если вам явно не по силам читать K&R, то вам явно еще рано претендовать на должность разработчика ПО.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Изменить настройки темы

Истории