Недавно сделав некоторую разработку для iPhone, я приехал, чтобы заметить, что интересный шаблон разработки использовал много в iPhone SDK, относительно объектной переменчивости.
Кажется, что типичный подход там должен определить неизменный класс NSFoo
, и затем получите из него изменяемого потомка NSMutableFoo
. Обычно NSFoo
класс определяет элементы данных, методы считывания и операции только для чтения и полученный NSMutableFoo
прибавляет методы set и видоизменяющиеся операции.
Будучи более знакомым с C++, я не мог не заметить, что это, кажется, полное напротив того, что я сделал бы при написании того же кода в C++. В то время как Вы, конечно, могли проявить тот подход, мне кажется, что более краткий подход должен создать сингл Foo
класс, методы считывания метки и операции только для чтения как const
функции, и также реализуют изменяемые операции и методы set в том же классе. Вы затем закончили бы с изменяемым классом, но типами Foo const*
, Foo const&
и т.д. все - эффективно неизменный эквивалент.
Я предполагаю, что мой вопрос, делает мое взятие на ситуации, имеют смысл? Я понимаю, почему Objective C делает вещи по-другому, но является там какими-либо преимуществами для подхода с двумя классами в C++, который я пропустил? Или я упускаю суть полностью?
Не чрезмерно серьезный вопрос - больше для моего собственного любопытства, чем что-либо еще.
Objective-C слишком динамичен. В C ++ квалификация const применяется во время компиляции, и любые нарушения квалификации const во время выполнения (например, изменение объекта с квалификацией const с помощью указателя, не квалифицированного константой) являются неопределенным поведением.
Отчасти это та же причина, по которой в Objective-C нет частных методов. Вы можете отправить любое сообщение любому объекту. Диспетчер времени выполнения принимает объект и сообщение и разрешает вызов реализации метода.
если бы const
квалифицированные объекты могли вызывать только квалифицированные методы const
, это полностью разрушило бы динамическую природу Objective-C и Foundation, потому что такая проверка должна была бы выполняться во время выполнения. (первая проверка будет определять, разрешается ли отправляемое сообщение в реализацию с квалификацией const для этого конкретного экземпляра, а другая проверка - чтобы определить, был ли сам экземпляр квалифицирован с помощью const). Рассмотрим этот теоретический пример:
NSArray *mutableArray = [[NSArray alloc] init];
NSString *mutableString = @"I am a mutable string";
const NSString *immutableString = @"I am immutable because I am const-qual'd";
[mutableArray addObject:mutableString];
[mutableArray addObject:immutableString]; // what happens?!
// and what happens here (both immutable and mutable strings would respond
// to the same selectors because they are the same class):
[mutableArray makeObjectsPerformSelector:@selector(aMutableOperation)];
Вы внезапно теряете динамику. В настоящее время изменяемые и неизменяемые объекты могут находиться вместе в неизменяемой или изменяемой коллекции.
Наличие изменяемого подкласса сохраняет динамическую природу Objective-C и упрощает выполнение. Некоторое время назад была похожая тема о частных методах.
Мысли...
Мак, как вы знаете, в C++, вы можете думать об "A" и "const A" как о двух различных типах, с их единственными отношениями
Компилятор обрабатывает наследование и распространение модификатора типа через выражения, и т.д.
Я бы предположил, что NS-специалисты выбрали соглашение ..Mutable... по нескольким причинам. Моя первая догадка заключается в том, что, как мне кажется, когда NextStep только зарождался, в C не было поддержки "const", и в нем все еще не было объектно-ориентированного подхода. И, что более важно, они хотели получить определенные оптимизации в своих реализациях изменяемых и неизменяемых объектов. Например, в классе неизменяемых строк, таком как NSString, может быть полезным "объединение" строк. Это позволяет распылять дубликаты строк и потенциально использовать меньше памяти. (Это имеет определенные недостатки, но всегда есть компромиссы.)
В C++ вы можете двигаться в том же направлении, сначала поняв copy-on-write. std::string, как говорят, делает это.
Interesting topic,
Уилл Брэдли