Шаблоны проектирования изменчивости в Objective C и C ++ - PullRequest
8 голосов
/ 10 июня 2010

Недавно, выполнив некоторые разработки для iPhone, я заметил интересный шаблон дизайна, который часто используется в iPhone SDK в отношении изменчивости объектов.

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

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

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

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

Ответы [ 2 ]

4 голосов
/ 10 июня 2010

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 и делает среду выполнения простой. Недавно была похожая тема о частных методах.

0 голосов
/ 10 июня 2010

Мысли ...

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

  1. «A» и «A &» могут быть неявно преобразованы в «const A» и «const A &» и т. Д. *
  2. "const A &" может быть от const_cast до "A &" и т. Д. *

Компилятор обрабатывает наследование и распространение модификатора типа через выражения и т. Д.

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

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

Интересная тема,
Уилл Брэдли

...