Есть ли способ обеспечить проверку типов во время выполнения в Objective-C на какао?
Привет я нахожу способ обеспечить проверку типа во время выполнения или такие вещи в Objective-C на какао.
Это мой пример кода. Я ожидал ошибку времени выполнения из-за неправильного присвоения переменной 'b'. Но это не так. Скомпилировано и выполнено без ошибок.
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSArray* a = [NSArray arrayWithObject: @"TEST"];
NSURL* b = [a objectAtIndex:0];
NSLog(@"Is this URL? %i", [b isKindOfClass:NSURL.class]);
[pool drain];
return 0;
}
// Console log after program execution:
// 2010-01-11 10:25:02.948 Type Checking[98473:a0f] Is this URL? 0
Я удивлен тем, что здесь нет проверки типов во время выполнения. Поскольку я использовал все языки высокого уровня, такие как VB, C#, Java, ActionScript... Я не знаю низкоуровневый язык, такой как C, поэтому я не уверен, что это правильный путь... Было действительно трудно понять почему нет ошибки компиляции или времени выполнения. Но я понимаю это как естественное правило в реальном мире Си. Но более строгая проверка типов мне очень поможет. Даже только в сеансе отладки. Есть какой-либо способ сделать это?
И если нет проверки типов во время выполнения, какую стратегию кодирования и отладки я должен использовать для неверно типизированных значений? И в чем заключается компромисс между проверкой типов во время выполнения или нет?
3 ответа
Objective-C имеет проверку типов во время компиляции для аргументов сообщений и возвращаемых типов, но он несколько слабее, чем во многих других языках. Одним из основных отличий является то, что классы коллекций, такие как NSArray и NSDictiomary, являются общими. Вы можете поместить любой тип объекта в NSArray - элементы не обязательно должны быть одного типа. Поэтому при добавлении или доступе к элементам проверки типов нет.
Нет проверки типов во время выполнения для назначения переменных. Я считаю, что это сокращение производительности. В общем, это не большая проблема. Если переменному присваивается неверный тип значения, в конечном итоге ему отправляется сообщение, которое он не понимает, что генерирует довольно полезное сообщение об ошибке.
Ну, есть проверка типов во время выполнения, но это происходит немного позже. Я предполагаю, что вы ожидаете какого-то исключения, когда пытаетесь поместить экземпляр NSString в переменную NSURL*. Вместо этого вы получите исключение, когда попытаетесь вызвать любые специфичные для NSURL методы в вашем экземпляре NSString.
Например, если вы попробуете [b isFileURL]
вы получите исключение типа "NSString не отвечает на селектор isFileURL".
Также важно понимать, почему в вашем примере нет проверки типов во время компиляции. В частности, отсутствие проверки типов во время компиляции является уникальным и важным свойством id
тип, который является то, что NSArray -objectAtIndex:
возвращается.
Платформа NSObject часто поднимает шум, когда тип неправильный, но вы можете вручную проверить тип и выдать исключение:
if (![obj isKindOfClass:SomeObjectClass.class])
[NSException raise:@"BadTypeException"
format:@"Bad type at line %d", (int)__LINE__];
[obj xyz];
...
if (![obj conformsToProtocol:@protocol(SomeProtocol)])
[NSException raise:@"BadTypeException"
format:@"Bad type at line %d", (int)__LINE__];
[obj abc];
Edit: удален предыдущий раздел, утверждающий, что вызовы несуществующих методов возвращают ноль или нули; как говорит Марк Бесси, исключение выдается (не возвращается ноль), если не ноль объект не реализует метод.