Лучший способ определить неизменный класс в Objective C

Я - новичок в Objective C, и я задавался вопросом, что лучший способ состоит в том, чтобы определить неизменный класс в Objective C (как NSString, например).

Я хочу знать то, что является основными правилами, за которыми нужно следовать для создания класса неизменным.

Я думаю что:

  • методы set не должны быть обеспечены
  • если свойства используются, они должны быть только для чтения
  • для "запрещения" Кодирования Значения ключа accessInstanceVariablesDirectly должен быть переопределением и возвратиться НЕТ

Я забывал что-то?

Спасибо

17
задан Patrick Marty 5 April 2010 в 01:27
поделиться

2 ответа

Первое и самое главное, что вам следует сделать, это включить в ваш файл .h комментарии по использованию, которые объясняют, что это неизменяемый класс, наряду с назначением класса и общими рекомендациями по использованию. Слишком часто люди идут на все, пытаясь «принудить» компилятор к тому, чего можно добиться, просто проинформировав вызывающего.

Вы, конечно, не должны предоставлять общедоступные сеттеры или свойства чтения и записи, если хотите, чтобы класс был неизменным (но, конечно, вы должны предоставить частные сеттеры, чтобы вы могли использовать аксессоры внутри класса; вам всегда следует избегать , даже внутренне, возиться с ivars напрямую, за исключением нескольких мест). Я предполагаю, что вы могли бы добавить свое переопределение accessInstanceVariablesDirectly , если бы вы увидели в этом вероятную ошибку со стороны вызывающей стороны.

Но ключ к пониманию Objective-C - это понять и принять тот факт, что вызывающий не является врагом. Вызываемый код не нужно «защищать» от вызывающего абонента. Вызывающий должен быть защищен от вероятной ошибки. Здесь все на одной стороне; звонящий и звонивший хотят, чтобы программа работала.

Вызывающий абонент является клиентом и должен рассматриваться как таковой. Покупатель не всегда прав, но покупатель всегда остается покупателем. Иногда это означает защиту клиента от самого себя, если он может допустить простую ошибку. NSAssert () особенно полезен для этого. А предоставление общедоступных установщиков неизменяемого класса почти заставляет вызывающую сторону совершить ошибку, так что это будет плохо для всех.

В любом случае, вы не должны усложнять свой класс, чтобы попытаться обеспечить неизменяемость. Вызывающий может почти (*) всегда нарушать инкапсуляцию, обращаясь к структуре напрямую ( объект-> ivar ). Звонящий поступил бы глупо, но еще глупее было бы попытаться предотвратить это. Обратите внимание на неизменность, скройте свои сеттеры и пометьте свойства только для чтения, и почти во всех случаях все будет в порядке.

(*) Да, можно еще больше скрыть ваши данные, вложив частную структуру / объект как ivar, но тогда вызывающий может изменить данные с помощью арифметики указателя, так что это еще не «принудительно». Всегда спрашивайте себя, какую проблему вы на самом деле пытаетесь решить.

13
ответ дан 30 November 2019 в 13:53
поделиться

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

Поскольку в Objective-C, по-видимому, нет окончательного способа определения класса как окончательного (запечатанного и т. Д.), Все, что вы могли бы сделать, на самом деле не является всеобъемлющим.

Я давно пришел к выводу, что вы действительно не можете использовать Objective-C, как если бы вы использовали Java, C ++ или C #. Objective-C просто слишком отличается. На самом деле я считаю, что существуют радикальные различия парадигм, такие как отправка / вызов статических и динамических методов.

Я упоминаю об этом потому, что, возможно, ни один класс в Objective-C не является действительно окончательным. Возможно, это связано с языковым дизайном, а не с тем, что вам следует пытаться обойти. Если вы это сделаете, вы в конечном итоге без нужды усложните свой код.

6
ответ дан 30 November 2019 в 13:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: