Pull to refresh

Comments 88

> Когда здоровый программист впервые видит вызовы методов в Objective C — у него выпадают глаза.
> Когда здоровый программист впервые видит вызовы методов в Objective C — у него выпадают глаза.
> Давай поговорим об этом.

Впечатление, что под катом ультрасовременные ловушки для выпадающих глаз :)

P.S. Какие-то горячие клавиши перехватили коммент до написания.
Ультрасовременная ловушка для выпадающих глаз — это Xcode 4.
findById — метод
Лейтенант педантичность возразит, название метода – findById:, двоеточие ставится потому как есть параметр
верно. Проапдейтил пост.
image->calculateSize

может я что-то не понял, но разве в Javascript обращение к методу не через точку (image.calculateSize)?
>masterpiece = [gallery findImageByWidth:400 andHeight:300];
>Вот так вызывается метод с двумя параметрами. Первый («400») названия не имеет, указывается сразу после имени >метода. Второй имеет название: andHeight.

Простите вы давно пишите на обжС ??? Apple Developer Library читаете ???

То что вы написали — не имеет с точки зрения ОбжС смысл. Тут вы ПЕРЕДАЕТЕ сообщение объекту gallery findByWidth:andHeight, но никак не вызываете метод у которого первый параметр без имени. Глупость.

>Objective C по-своему прекрасен.
А тут согласен на все 100. Ключевое слово: «по своему»
>см. PS.
Если это статья для начинающих, то зачем тогда Вы засоряете им мозг изначально неправильными формулировками?
Когда писал PS не было. А зачем тут начинающим мало того что такой скупой кусок информации, так и вдобавок изначально формирует у них неправильное восприятие и понимание языковых конструкций???

Так потом я появляются кодеры, доказывающие что первое есть название «МЕТОДА», у которого первый параметр не имеет название.

PS: Извините ничего личного не имею, просто задело немного за «живое». Считаю лучше привести список полезной литературы для начинающих, которая опробована в боях так сказать или помогла разобраться с проблемой. А то когда сам начинал писать чтолько пришлось перелопатить книг, пока нашел стоящие
>Так потом я появляются кодеры
Сорри не заметил вместо «я» И должно стоять
Ну так напишите в комменте, как правильно
В общем-то уже писали. Это часть имени метода, а не название аргументов
Зачем ставить три знака вопроса???
Это степень ненависти:
1. Вопрос
2. Вопрос с пощечиной
3. Вопрос и прозженный стул
Гы. Как раз хотел спросить автора, почему не называть методы подобно селекторам в Smalltalk-е, как увидил ваш комментарий и все стало на свои места :)
А вот мой постскриптум, значит, недостаточно ясно этот вопрос освещает, так?
Мне кажется «по своему» тут как раз лишнее.
Дабы усложнить всем восприятие, дополню, что Objective C позволяет и никак не называть параметры:

- (void)funkyMethod:(int)param1 :(int)param2 :(int)param3;


с соответствующим вызовом:

[object funkyMethod:1 :2 :3];


Но хочу отметить, что такая нотация используется крайне редко.
ух ты, не знал, спасибо. Ес-но, такая нотация нечитаема.
Мне очень сильно кажется, что ранее такой синтаксис имел смылс (в том плане, что в отличии от С имел место не вызов метода, а отправка сообщения), а сейчас просто приобрел статус сакрально-жреческого — мол так надо и все.

Но мой взгляд — не сильно удобный синтаксис вызова метода. Все эти скобки [] — сильно лишние, ИМХО :-)

Если как в примре — передавать захардкоженные значения- то да, возможно. Но в реальной жизни передают значение переменных, которые и так имеют имена.

Если я не ошибаюсь, то где-то видел в сети, что новая версия ОбжЦ позволяет делать вызовы а-ля .NET?

obj.method(arg1, arg2)

зачем? тут все рпосто очень удобно — не привычно, но удобно

[[MyCall alloc] initX:3 y:4 addition:myObj]
А в твоем варианте
MyCall.alloc().initX_Y_Addition(3, 4, myObj)
Глупый пример. Передавать числа в метод, а не переменные — это очень нетрадиционный способ писать код.

А если передавать переменные, которые обычно имеют «говорящие» имена, то зачем передавать их с доп описанием?

они прямо всегда такие говорящие? А как вы метод выбирать будите?

В С++ я иногда вообще завожу временные переменные только ради того, что можно было прочитать код с ходу, несмотря на сигнатуру объекта.

Пример: метод set(obj a, book check_obj).
использование метода совсем непонятно. obj.set(otherObj, true);

В общем это надо попробовать, и в нормальной среде — мне тоже казалось это не нужно.
Вы уж извините, но как то у Вас мысли разбросаны, и логическая мысль не всегда ясна, как «вилами по воде». Закралось мысль, что эта статья, как взгляд первоклашки на новую программу образования))) Без обид.
Вы бы хоть википедию почитали бы — описание того, как работает obj-C.
Всё названное вами методами методами и не является. Если для новичков, то зачем вводить их в заблуждение?
К том же не для аудитории хабра эта статья — уровень здесь повыше.

/новичок в objective-C, 4 месяца/
Ну почему же методами не является.
Метод/сообщение — это одно и тоже название 2 разных вещей
Ну, как-то так — тут меня, видимо, приклинило. Собственно претензия к уровню статьи всё равно остаётся.
Метод и сообщение отличаются друг от друга.

В ООП есть две школы того, как делается обращение к объекту.

Первая (C++-школа) предполагает, что метод, который мы вызываем, является неотъемлемым свойством объекта. Мы выбираем метод среди всех полей объекта (в C++ оператор '->' официально даже называется «селектор», если я ничего не путаю), а затем вызываем его. Самое главное здесь в том, что метода не существует, если объект равен null, т. е. ситуация, когда мы пытаемся вызвать метод на null, эквивалентна ошибке.

Вторая (Smalltalk-школа, именно этот подход реализован в Objective C) предполагает, что сообщение отделено от объекта, который его получает. Объект, получив сообщение, может на него отреагировать или нет. Поэтому, кстати, если вы в *.h забыли вписать сигнатуру метода, реализованного в *.m, то в том месте, где вы его вызываете, будет не ошибка компиляции, а всего лишь предупреждение — есть другие способы перехватить сообщение, кроме как посредством реализации метода. Ещё одно отличие состоит в том, что отправка сообщения объекту nil является допустимой. А в самом Smalltalk nil — это вообще объект, экземпляр класса Nil.

Так что не путайте сообщение с методом, это не одно и то же.
в python't это называется методом, но ведет он себя вполне по Smalltalk'овски

Это динамическая и статическая типизация, а не…
В Objective C она статическая (программист указывает тип переменных, и контроль типов производится на этапе компиляции), что не лишает возможности иметь смолтоковские сообщения, а не методы.

В Питоне, кстати, можно вызвать метод на None (в смысле, я серьёзно не знаю)?
Можно. Он скажет что ты сам дурак. у none методы вызывать нельзя

А вот и не статическая. Она частично статическая, пока ты не перешел к объектам
Ну это вопрос того, где граница определения динамической и статической типизации. Классическое определение статической: «такая, где переменные (а не только значения) имеют типы». В этом смысле в Objective C статическая.

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

Но мы ушли в сторону, предлагаю на этом закончить.
Отчего это у None нельзя вызывать методы? Как тогда print None работает?

Пожалуйста: print None.__str__(), None.__hash__()
Это я про Python, конечно же.
В Objective C он тоже называется селектором.
Это очень далеко от правды. Метод нельзя вызвать у nil'а (null'а), послать сообщение nil'у — обычное дело. Метод — вызвается только тогда, когда он определен у объекта, сообщение можно послать объекту любое.

Разница часто не ощущается, но она есть и огромна. Другое дело, что в Objective-C есть и методы, и реализации, и процедура передачи сообщения. Все это зафиксировано в документации и имеет свое значение. К сожалению, часто все это путается. К еще большему сожалению, видимо, это плохая категоризация и сами Apple-специалисты умышленно путают эти понятия.

Ну и про название селектора/параметров… тоже не все так просто.

/Жаль, что много таких ошибок, поначалу показалось, что хорошая статья, хотел попросить ее для TouchDev.ru/
почитал. вроде бы как раз здесь это синонимы, так как посылка сообщения является синхронной — это, по сути, вызов метода и есть, что-то типа вызова виртуального метода в С++, с поиском нужной функции в таблице — в отличии, например, от посылки асинхронного сообщения оконному объекту в Windows, когда сообщение вместе со всеми параметрами ставится в очередь, а объект прочитает его, когда ему вздумается.
поправьте, так как неспециалист
Не совсем. Просто в терминах Smalltalk правильно сказать послать сообщение и дождаться реакции, а в терминах С++ и питона — вызывать метод

А вот оконные сообщения — это уже СОВСЕМ другая история
методы — это синхронные сообщения. и не надо тут высасывать из пальца разницу. её нет. точно также при отсутствии метода может вызываться другой. точно также значение означающее «нет данных» может являться объектом со всеми вытекающими.
Позвольте не согласиться про «не для аудитории». Я с удовольствием читаю хабр, статьи разного уровня сложности. Впервые увидев синтаксис языка ужаснулся. После статьи повторно уже буду смотреть на него по-другому. Автору большое спасибо, даже если как сказано в отзывах все не совсем так.
А вообще это часть имени метода, а не имя параметры!
спасибо за разъяснения, два дня назад впервые увидел код на Objective C. Пойду искать выпавшие глаза
> Когда здоровый программист впервые видит вызовы методов в Objective C — у него выпадают глаза.

Да что вы! Отличный язык для расширения сознания. Не сильно отстаёт от хаскеля, схемы и пролога в этом плане. ;)
это просто тенденция модная такая — языки ругать
lisp и ему подобные — много круглых скобок
objective-c — много квадратных скобок
python — не хватает фигурных скобок
и т.д.
UFO landed and left these words here
Насколько я понимаю (увы, objective-c не является моим профильным языком) там нет методов и аргументов, есть только сообщения и их параметры. Если проводить аналогию с javascript, то выглядеть это должно примерно так:

//  "Метод без параметров"
 
//  Objective-c, на самом деле это "сообщение без параметра"
-(void ) Foo {}
[ o Foo ]
 
//  Javascript
= {}
o[ "Foo" ] = function() {}
o[ "Foo" ]()
 
//  "Метод с одним аргументом"
 
//  Objective-c, на самом деле это "сообщение с параметром"
-(void ) Foo : (int) a {}
[ o Foo : 1 ]
 
//  Javascript
= {}
o[ "Foo" ] = function( a ) {}
o[ "Foo" ]( 1 )
 
//  "Метод с двумя парметрами"
 
//  Objective-c, на самом деле это "сообщение с параметром" и
//  ЕЩЕ ОДНО "сообщение с параметром"
-(void ) Foo : (int) a Bar : (int) b {}
[ o Foo : 1 Bar : 2 ]
 
//  Javascript
= {}
o[ "Foo" ] = {}
o[ "Foo" ][ "Bar" ] = function( a, b ) {}
o[ "Foo" ]( 12 )
 


То есть то, что идет после -(void) — это не «имя функции, имя аргумента, имя параметра, имя второго аргумента, имя второго параметра» а «первое сообщение с параметром, второе сообщение с параметром» итд.
Это все имя сообщения. оно может состоят из несокльких кусков
Нюансы реализации. Понятное дело в скомпилированно .exe нету «Графа со строковыми именами сообщения и параметра» — там нечто вида «Foo(int)Bar(int) которое, к тому же, преобразовано в индексы, которые используются при вызова, а имена — только при вызове селектора по имени через @selector
Там есть Foo:Var: и его селектор
Сообщение будет называться FooBar.
См. выше. Я упростил пример, дабы не вдаваться в нюансы про «сигнатуру сообщения», преобразования итд. Лично мне при программировании логически оперировать «кучкой сообщений» проще, чем «сигнатурой сообщеия». Синтаксис сразу становится такой простой и понятный :)
o[ "Foo" ][ "Bar" ] = function( a, b ) {}
o[ "Foo" ]( 1, 2 )


не заработает это.
Капитан, не узнал Вас в гриме :) Нк понятно же что очепятка и там должно быть o[ «Foo» ][ «Bar» ]( 1, 2)
[gallery findImageByWidth:400 andHeight:300]

лучше бы сделали так:
[gallery, find me image by width equal to 400 add height equal to 300 ]

x)

но если серьёзно, то лучше бы смотрелось [gallery findImageBy width:400, height:300]
без необходимости помнить точный порядок параметров и заполнять недостающие нуллами.
Почитайте про Smalltalk. И поймете почему так. Ну или хотя бы про сам ObjC.
О, Егор, спасибо, как раз очень вовремя ты то написал, один глаз как раз был уже навыкате.
Не, ну ты видишь к чему придрались, а?:) Ну как тут захотеть что-то дальше писать?:)
Как раз синтаксис и вызовы селекторов вызывают меньше всего сложностей у начинающих.

Обычно до всех очень сложно доходят все эти retain/release/autorelease — хотя казалось бы, обычный подсчет ссылок.
Аха. На собеседовании ни один из кандидатов не смог с уверенностью сказать где и когда будет освобождена NSString a = @«Засада»; :)
В смысле «когда и где будет освобождена»? Правильный ответ — «по завершению программы»?
правильный ответ – ошибка, т.к. наследники NSObject создаются только в куче
Ответьте пожалуйста сами на свой вопрос: «когда освободится aaa=@»ZZZ"?

Если я сам что-то понимаю в ObjC, 'aaa' — это статический объект, и эта конструкция равна const char* aaa = «ZZZ», т.е. никакого «освобождения» нет и быть не может, потому что нет никакого создания.
См. ниже. Это конечно не совсем аналог «char* a», это статический экземпляр класса NSString. Более того, NSString* a = @«Засада»; NSString* b = @«Засада»; создаст ОДИН статический объект типа NSString со значением «Засада» и указатель на него будет положен в a и b.
Ну, это очевидные вещи, имхо, что a и b будут одним и тем же указателем.
Не, это я звездочкой очепятался :). Хотя, вообщем-то, такое на собеседованиях тоже никто не замечал :(. Так что autorelease pools — это жопа сила.
В целом да, ответ правильный. Но никто не сказал, что @«что-то-там» создает сатический объект типа NSObject на этапе компиляции и что данные объекты не помещаются в 'autorelease pool'. Соответственно, на провокационный вопрос «а будет ли строка @»Засада"" помещена в autorelease pool все отвечали «не знаю» :(.
Это садистский провокационный вопрос. Ясен пень, что это статический объект, и также естественно, что он не появляется ни в каком autorelease pool, потому что класть его туда некому и не зачем (кстати, тоже провокация — «а кем создается этот NSString? А если отключить все библиотеки и собрать голый main.m, будет работать?»)

Или всю эту очевидную пургу надо явно проговорить на вашем собеседовании?
На собеседовании ничего не надо проговаривать — я задавал много разных вопросов и смотрел смогу я с этим человеком работать или нет. Нанятый мною программист не ответил на этот вопрос, также как и все :). BTW, ну что в этом вопросе провокационного? Я пишу на листочке бумаги «NSString* a = @»Засада";" и спрашиваю — «Когда освободится память, в которой алоцирована эта строка?» Ответ «по завершению программы» меня вполне устроит. Ответ «в autorelease pool» устроит меньше. Ответ «не знаю» меня немного огорчит :(. ИМХО, У программиста должно быть хотя бы примерное понимание о жизни создаваемых им конструкций. Пусть даже неправильное — это я на code review ему объясню. Но если человеку не интересно когда освобождается память — у него будут мемори лики которые потом будут долго и мучительно чиниться.
У меня от квадратных скобок глаза выпадают, а вот с вызовами проблем нет. В Python так же можно.
myStupidObject.my_stupid_method('spam', keyword='eggs', length=100500)
Не хочу разводить холивар, но на мой взгляд такой вариант лучше читается — меньше визуального мусора.
Я когда только начал изучать питон, сразу же «вьехал» в такую нотацию. А с ОбжЦ нужно прочитать целую статью, чтобы только понять как передать параметр в функцию. :)
Кроме того, у питона есть еще один плюс: объявление функции и ее вызов очень похожи, вплоть до того, что можно скопировать и подправить.
Например в питон:
— обявление: def findImage(width, height=300, tag=None): — если нужно, сразу можно дать параметры по умолчанию
— вызов: findImage(width=400, heigth=500)

Может обжц объявление имеет свои плюсы, но на мой взгляд, оно намного сложнее. А простота чтения и записи — это большой плюс для ЯП
Когда здоровый программист впервые видит вызовы методов в Objective C — у него выпадают глаза.

вполне выразительный и читабельный язык, например:
if ([здоровыйПрограммист видитВпервые:objectiveC.вызовМетода]) {
    [здоровыйПрограммист.глаза выпадают];
}


* This source code was highlighted with Source Code Highlighter.
:-D

Ну вот если так внятно писать, то тогда читаемый.
Иногда создаётся впечатление, что некоторые языки программирования создавались в первую очередь для того, что бы удивить мир своим синтаксисом.
Да нет, чтобы быть совместимыми по синтаксису с 'C' :)
Я тоже долго привыкал к синтаксису ObjectiveC после Java. Но я бы сказал что для меня бОльшей проблемой стал не синтаксис — а то что наличие методов и их параметров не проверяются компилятором. Другими словами, если ты вызвал метод какого-то объекта — но забыл его определить и написать — компилятор не будет ругаться. Java мне в этом плане гораздо больше нравится.
Так ведь это не вызов метода, а передача сообщения. Сообщение можно послать nil'у; любой инстанс не обязан реагировать на сообщения; и т.д. Тут чуть выше развели небольшой холиварчик на эту тему.

Это — идеология. У нее есть плюсы и есть минусы.

А warning таки будет, компилятор не пропустит такой спорный момент.
варнинги — это костыли.
если я написал верный код, но на него выдаётся варнинг, то тут есть два варианта:
1. как-то сказать компилятору что всё нормально, успокойся. но тогда компилятору лучше выдавать ошибку и требовать от программиста разрулить неоднозначночть.
2. не обращать внимания. тогда процесс компиляции будет завален варнингами и возможная ошибка может пролезть незамеченной.
вывод: никаких варнингов, нотисов и прочей фигни быть не должно. если компилятор не уверен, в правильности кода — это ошибка. без вариантов.
Не надо ходить с собственным уставом в чужой монастырь. Повторюсь — отнюдь не глупые люди придумали передачу сообщений. А то, что вы говорите — это слшиком очевидно, чтобы за двадцать лет не всплыть в светлых головах.
у людей очень избирательное мышление — они не видят то, что не хотят видеть. и чем больше времени прошло тем больше уверены, что так и надо.
Sign up to leave a comment.

Articles