Подтвердить что ты не робот

Почему NSNumber неизменен?

Почему NSNumber неизменяемый? Была ли веская причина? Потому что теперь я думаю о создании своего собственного класса только ради изменчивости.

4b9b3361

Ответ 1

Число - очень простой тип данных. Число это просто - номер. Если вы его мутируете, это просто нечто другое. Число просто не может измениться.

Сравните это с более сложными данными, где сам объект по-прежнему представляет одно и то же.

Ответ 2

Неизменяемые номера экономят пространство. Предположим, что ваша программа создает много NSNumber s, и большинство из них - маленькие числа, такие как 0 или 1. С неизменяемыми числами вам нужны только несколько объектов, по одному для каждого отдельного значения. С изменчивыми числами у вас столько объектов, сколько у вас есть.

Неизменяемые номера легко разделить. Предположим, что вы завершаете примитивное число (например, int) с помощью NSNumber. С неизменяемым NSNumber компилятор всегда уверен, что значения соответствуют, поэтому он может разворачивать его и передавать примитивное значение в функцию, ожидающую примитивного значения. С изменением NSNumber вы не можете быть уверены, что другой поток не изменил значение и должен действительно разворачивать его каждый раз или даже думать о синхронизации. Это становится более дорогостоящим, если значение передается все дальше и дальше в вложенных вызовах.

Неизменяемые объекты имеют много других полезных свойств: они являются хорошими хеш-ключами, их время жизни и область действия легче определить и т.д. Многие функциональные языки, например. Erlang или XSLT, имеют только неизменные структуры данных.

Ответ 3

Эйко делает хорошую точку: NSNumber представляет собой базовый тип данных, и нет смысла его изменять.

Ему нравится иметь int i=0; и спрашивать, почему 0 не изменяет. И в OS X Lion x64 именно для целых чисел, поскольку NSNumbers реализованы как тегированные указатели, которые являются указателями, которые содержат данные вместо адреса,

Пример: скажем, мы хотим сохранить целое число 42 в указателе. Мы могли бы создать NSNumber, а затем указать на него, или мы могли бы заменить адрес на 42, и в этом случае мы можем пропустить создание объекта. Но как мы можем сказать, имеем ли мы дело с общим указателем или указателем с тегами?

Указатель x86 64 имеет 64 бита, но использует только 48 бит для адреса указателя. Причина в том, что 48 бит обеспечивает адресное пространство 256 ТБ, что очень много. Использование 64 бит было бы расточительным, потому что для CPU потребовалось бы больше транзисторов. Таким образом, потенциальное адресное пространство составляет 64 бит, но текущие процессоры могут использовать только 48. Из-за этого конечные биты указателя равны 0, потому что они остаются неиспользованными. Мы используем эти последние биты, чтобы указать, что указатель представляет собой тег с указателем, который представляет целое число с заданным количеством бит.

Следовательно, OS X NSNumber, представляющий целое число, буквально представляет собой целое число, но среда выполнения может обнаруживать ее как помеченный указатель и представлять ее пользователю как общий экземпляр.

Для других числовых типов реализация является более сложной, как видно из бесплатной альтернативы Core Foundation NSNumber CFNumber.

Ответ 4

Я думаю, что у всех был хороший ответ, кроме, может быть, 9000. Не уверен, о чем он говорит, хотя, возможно, это просто над моей головой.

Решение сделать NSNumber неизменным является дизайнерским решением создателей Foundation Framework. Я думаю, мы все можем согласиться на это.

Я предполагаю, что причина в том, что все объекты, созданные в Objective-C, ссылаются с помощью указателей, включая NSNumber. Это вызывает некоторые проблемы с дизайном при передаче NSNumber. Скажем, вы создаете класс под названием "Человек" с свойством NSNumber "myAge". Таким образом, ваше приложение создает экземпляр Person и устанавливает myAge в 28. Некоторая часть приложения теперь запрашивает объект Person для своего возраста и возвращает (NSNumber *) myAge или указатель на объект NSNumber, который обертывает значение 28 Поскольку указатель был передан, ваш объект Person теперь должен задаться вопросом, изменила ли эта другая часть приложения значение myAge!

Таким образом, NSNumber является неизменным, поскольку это объект, предназначенный для хранения значения, которое может быть создано, извлечено и передано вашим приложением как значение, а не как уникальный объект.

Ответ 5

Я предполагаю, что он неизменен, как и другие классы (NSArray, NSString и т.д.), поскольку неизменяемые объекты проще в использовании и обмениваются и передаются в поточном коде. См. wikipedia.

Ответ 6

Пример подкласса NSNumber

Примечание: в документации говорится, что objCType и атрибут value реализованного типа (intValue здесь) должны быть реализованы.

Это делается здесь с назначенным инициализатором (-) init... но это может быть сделано с помощью метода (+).

@interface NSMutableNumber : NSNumber
{
    int intValue;
}
@property const char *objCType;
+ (id) mutablenumberWithInt:(int)value;
@end

@implementation NSMutableNumber
@synthesize objCType;
+ (id) mutablenumberWithInt:(int)value {
    return [[self alloc] initWithInt:value];
}
- (id) initWithInt:(int)value {
    if (self=[super init]) {
        intValue=value;
        objCType="i";
    }
    return self;
}
- (int)intValue {
    return intValue;
}
- (void)setInt:(int)value {
    intValue=value;
}

@end

Тогда

    NSMutableNumber *mutn=[NSMutableNumber mutablenumberWithInt:2];
    NSLog(@"%@\n", mutn);

    // return 2

    [mutn setInt:4];
    NSLog(@"%@\n", mutn);

    // return 4