2010-06-09 6 views
8

Недавно сделав некоторую разработку для iPhone, я заметил замечательный шаблон дизайна, который много использовал в iPhone SDK, касающийся изменчивости объекта.Шаблоны проектирования Mutability в Objective C и C++

Кажется, что типичный подход заключается в определении неизменяемого класса NSFoo, а затем вытекает из него изменчивый потомок NSMutableFoo. Как правило, класс NSFoo определяет члены данных, геттеры и операции только для чтения, а производные NSMutableFoo добавляет к сеттерам и мутирующим операциям.

Будучи более знакомым с C++, я не мог не заметить, что это похоже на полную противоположность тому, что я делал бы при написании того же кода на C++. Хотя вы, конечно, может принять этот подход, мне кажется, что более кратким подходом является создание одного класса Foo, маркирования геттеров и операций только для чтения как функций const, а также реализации изменяемых операций и сеттеров в том же классе , Затем вы закончите с изменяемым классом, но типы Foo const*, Foo const& и т. Д. Все это фактически непреложный эквивалент.

Я думаю, мой вопрос в том, имеет ли смысл воспринимать ситуацию? Я понимаю, почему Objective-C делает вещи по-другому, но есть ли какие-либо преимущества для двухклассового подхода на C++, который я пропустил? Или я пропущу точку целиком?

Не слишком серьезный вопрос - больше для моего собственного любопытства, чем что-либо еще.

ответ

4

Objective-C является слишком динамичным. В C++ const-qualification применяется во время компиляции, и любые нарушения сост-квалификаций во время выполнения (такие как модификация объекта, сконструированного с помощью const, с помощью указателя, не содержащего константы) - это неопределенное поведение.

Отчасти это связано с тем, что в Objective-C нет частных методов. Вы можете отправлять любое сообщение, которое хотите поместить на какой-либо объект. Рассылка во время выполнения принимает объект и сообщение и разрешает реализацию метода для вызова.

если const квалифицированные объекты могут вызывать только const квалифицированных методов, было бы полностью разрушить динамический характер Objective-C и Фонда, поскольку такая проверка будет необходимо сделать во время выполнения (первая проверка будет определить, является ли сообщение, отправленное раздела решает для реализации, специфичной для 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 и обеспечивает простоту выполнения. Недавно была аналогичная тема о частных методах.

0

Мысли ...

Mac, как вы знаете, в C++, вы можете думать «А» и «сопзЬ А» в виде двух различных типов, с их только отношения будучи

  1. " а»и "&" может быть неявно приведен к "сопзЬ а" и "константные A &", и т.д ...
  2. "Const &" может быть const_cast к "&", и т.д ...

Компилятор обрабатывает наследование и распространение модификатора типа с помощью выражений и т. Д.

Я бы предположил, что люди NS выбрали соглашение ..Mutable .. по нескольким причинам. Мое первое предположение заключается в том, что я считаю, что, когда NextStep изначально был первопроходцем, у C не было поддержки «const», и у нее по-прежнему нет Object-Orientation. И что еще более важно, они нуждались в определенных оптимизациях в своих реализациях с изменчивыми и неизменяемыми объектами. Например, в неизменяемом строковом классе, таком как NSString, может быть полезно «пул» строк. Это позволяет распылять повторяющиеся строки и потенциально использовать процесс с меньшим объемом памяти. (У него есть некоторые недостатки, но всегда есть компромиссы.)

В C++ вы могли головой в том же направлении, сначала понимая copy-on-write. std :: string, как говорят, делает это.

Интересная тема,
Will Bradley

+1

'std :: string' разрешено использовать COW для сохранения при копировании, но не требуется для этого стандартом. Поскольку COW на самом деле является хитом производительности в многопоточной среде, некоторые реализации все еще делают это. –

 Смежные вопросы

  • Нет связанных вопросов^_^