Ключ к проблеме, с которой вы столкнулись, лежит в тонком замечании о полиморфизме в Objective-C. Поскольку язык не поддерживает перегрузку методов, предполагается, что имя метода уникально идентифицирует метод в данном классе. Существует неявное (но важное) предположение, что переопределенный метод имеет ту же семантику, что и метод, который он переопределяет.
В данном случае, возможно, семантика двух методов не одинакова; то есть первый метод возвращает новую строку, инициализированную «раздетой» версией содержимого получателя, тогда как второй метод непосредственно изменяет содержимое получателя. Эти две операции действительно не эквивалентны.
Я думаю, что если вы внимательно посмотрите, как Apple называет свои API-интерфейсы, особенно в Foundation, это действительно поможет пролить свет на некоторые семантические нюансы. Например, в NSString есть несколько методов для создания новой строки, содержащей измененную версию получателя, например
- (NSString *)stringByAppendingFormat:(NSString *)format ...;
Обратите внимание, что имя является существительным, где первое слово описывает возвращаемое значение, а остальная часть имени описывает аргумент. Теперь сравните это с соответствующим методом в NSMutableString для добавления непосредственно к получателю:
- (void)appendFormat:(NSString *)format ...;
В отличие от этого, этот метод является глаголом, потому что нет возвращаемого значения для описания. Поэтому из одного только имени метода ясно, что -appendFormat: действует на получателя, тогда как -stringByAppendingFormat: нет, и вместо этого возвращает новую строку.
(Кстати, в NSString уже есть метод, который выполняет хотя бы часть того, что вы хотите: -stringByTrimmingCharactersInSet:
. Вы можете передать whitespaceCharacterSet
в качестве аргумента для обрезания начальных и конечных пробелов.)
Так что, хотя поначалу это может показаться раздражающим, я думаю, что в долгосрочной перспективе вам действительно стоит попытаться подражать соглашениям Apple об именах. Если ничего другого, это поможет сделать ваш код более самодокументированным, особенно для других разработчиков Obj-C. Но я думаю, что это также поможет прояснить некоторые семантические тонкости Objective-C и фреймворков Apple.
Кроме того, я согласен, что внутренние детали кластеров классов могут сбивать с толку, тем более что они в основном непрозрачны для нас. Однако факт остается фактом: NSString - это кластер классов, который использует NSCFString как для изменяемых, так и для неизменяемых экземпляров. Поэтому, когда ваша вторая категория добавляет другой метод -strip
, он заменяет метод -strip
, добавленный первой категорией. Изменение имени одного или обоих методов устранит эту проблему.
И поскольку в NSString уже существует метод, обеспечивающий те же функции, возможно, вы могли бы просто добавить изменяемый метод. В идеале его имя будет соответствовать существующему методу, поэтому оно будет:
- (void)trimCharactersInSet:(NSCharacterSet *)set