#objective-c #cocoa #dynamic-typing
#objective-c #какао #динамическая типизация
Вопрос:
Я составляю список вопросов для собеседования для кого-то, кто хочет стать разработчиком Cocoa. Я программист, но я никогда не делал Objective-C. Я наткнулся на интересный вопрос, который включает динамическую типизацию. Это должно быть элементарно, я попробовал и скомпилировал его, но я все еще не уверен, как и почему это работает.
Вопрос в том
Что происходит во время компиляции и во время выполнения, когда вы выполняете следующее:
NSString *s = [NSNumber numberWithInt:3];
int i = [s intValue];
В отладчике я получаю
i = (int) 3 s = (__NSFCNumber *) 0x383 (недопустимый адрес)
Вывод NSLog(@"%d",i)
есть 3
, а вывод NSLog(@"%@",s)
есть 3
.
Может кто-нибудь дать мне объяснение того, как все это обрабатывается компилятором и системой выполнения, также пытаясь иметь в виду, что я совершенно новичок в Objective-C и Cocoa, но совсем не новичок в информатике?
Ответ №1:
Ваш s — это просто стандартный указатель C, которому присваивается NSNumber
объект (указатель на a).
NSNumber
, а также NSString
, отвечает на intValue
. Вот и все.
Комментарии:
1. Дополнительный комментарий по поводу интервью: любой хороший программист может выучить любой язык, поэтому меня больше интересует понимание возможностей интервьюируемых, чем их знаний. Вопросы тестового типа, которые я ненавижу, хотя те, что указаны в вашей ссылке, в основном являются хорошим началом для разговора.
2. Ваше последнее предложение — это то, чего мне не хватало. Я не понимал, что оба типа отвечают
intValue
.3. Что касается вопросов для интервью, я полностью согласен. Обычно я не провожу собеседования с людьми, задавая им вопросы тестового типа, но мы ищем разработчика iPhone, и никто в компании не разбирается в программировании iPhone, поэтому я просто пытаюсь понять, насколько они разбираются в концепциях. Вот почему я прибегаю к стандартному типу интервью с вопросами и ответами, но спасибо за совет. Ваша точка зрения очень верна.
Ответ №2:
s
указатель, который вы объявили, будет указывать на NSString
объект. Он может указывать на что угодно, но в идеале он должен указывать на NSString . Однако пример кода s
указывает на объект NSNumber .
Пока вы отправляете только методы s
, которые являются методами, которые NSNumber
реагируют на все нормально (за исключением, может быть, предупреждений компилятора). Если бы вы попытались отправить метод NSString этому объекту, на который указывает, s
что NSNumber не отвечает, вы бы получили исключение. Если объект имеет соответствующую сигнатуру селектора (т. Е.: @selector(intValue)
), Будет вызван метод.
Комментарии:
1. Не совсем правильно, поскольку intValue на самом деле является методом в NSString. Возможно, лучше сказать, что и NSNumber, и NSString реагируют на сигнатуру (или значение @selector) intValue .
Ответ №3:
Объявление NSString для переменной «s» выполняется просто для того, чтобы помочь компилятору интерпретировать ваше намерение переменной «s». Это позволяет компилятору принудительно выполнять статическую проверку типов в случае, когда вы намеревались использовать переменную определенного типа, но случайно назначили переменную другого типа. В ObjC переменная может указывать на любой объект, в то время как синтаксис скобок является средством отправки «сообщения» объекту. Отправка сообщения предписывает компилятору сгенерировать код, который ищет функцию, реализующую сообщение. Также в ObjectiveC сообщения называются селекторами. (Детали низкого уровня немного сложнее, но на высоком уровне так оно и работает.) Это динамическая часть dynamic typic, которую также называют «утиной типизацией». Идея в том, что если он выглядит как утка, вы должны быть в состоянии заставить его крякать, как утка. По сути, любому объекту, который соответствует определенной форме, может быть присвоен тип, соответствующий форме.
Рассмотрим следующее:
Dog *myPuppy = [[Cat alloc] init] autorelease];
[myPuppy walk];
Food *preparedDish = [self prepareMealForPet];
[myPuppy eat: preparedDish];
Компилятор пометит вас здесь, указав, что вы намеревались провести время с собакой, но на самом деле имеете дело с кошкой. Однако это совершенно справедливо, поскольку кошка имеет форму, похожую на собаку, в том смысле, что они оба могут ходить и есть готовые блюда. Утиный ввод позволяет вам избежать этого, поскольку во многих случаях вам нужно будет принимать типы переменных, которые заранее неизвестны. Кроме того, с помощью самоанализа вы можете обнаружить форму вашего объекта во время выполнения. Рассмотрим в приведенном выше коде, хотим ли мы попросить нашего щенка лаять. Мы получим исключение, и приложение завершит работу. Однако мы могли бы использовать самоанализ, чтобы спросить, отвечает ли наш объект на сообщение «bark», чтобы избежать сбоя.
if([myPuppy respondsToSelector:@selector(bark)]) {
[myPuppy bark];
}