«Обобщения» в Objective-C, чтобы сделать RangeValidator? - PullRequest
2 голосов
/ 23 марта 2012

В C # я мог бы сделать это:

class RangeValidator<T> {
    public T MinValue { get; set; }
    public T MaxValue { get; set; }
}

Где T может быть любого типа примитива;int, float, double ... или любой тип объекта;String, DateTime и т. Д.

Если бы в Obj-C я сделал это так:

@interface RangeValidator {
    id minValue;
    id maxValue;
}
@property ...

Это будет работать, скажем, для NSNumber или NSString, но если яназначив NSInteger для minValue, я получу что-то вроде

warning: initialization makes pointer from integer without a cast
// Since an id is a pointer to an object, not an integer. Correct?

Очевидное решение здесь, может быть, вместо этого использовать NSNumber.Мне было просто любопытно, есть ли другие способы решения этой проблемы?

Спасибо!

Ответы [ 3 ]

2 голосов
/ 23 марта 2012

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

Приведенный выше код не работает, потому что NSInteger является typedef для соответствующего типа примитива, а не типа указателя. Вместо этого вы должны использовать оболочку NSNumber.

2 голосов
/ 23 марта 2012

Правильным способом было бы использовать NSNumber и инициализировать из целого числа с помощью

[NSNumber numberWithInt:someInt];

Таким образом, классу не нужны универсальные шаблоны, вы можете легко выполнить проверку, проверив, если minValue иmaxValue например, понимает intValue (или, может быть, какой-то селектор сравнения, в зависимости от того, что вы хотите сделать).

if([minValue respondsToSelector:@selector(intValue)]) {
    return [minValue intValue];
} else {
    ....
}
1 голос
/ 23 марта 2012

Я думаю, что идиоматическое решение Objective-C будет именно тем, что вы предлагаете, используйте тип id и оберните значения примитивных чисел в NSNumber. NSInteger, как упоминает Константин, является примитивным типом - см. Справочник типов данных Foundation :

#if __LP64__ || TARGET_OS_EMBEDDED || TARGET_OS_IPHONE || TARGET_OS_WIN32 || NS_BUILD_32_LIKE_64
typedef long NSInteger;
#else
typedef int NSInteger;
#endif

Это несоответствие между примитивными типами и объектами немного прискорбно, вы должны научиться распознавать не-объектные типы, такие как NSInteger, CGRect или CMTime.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...