Почему [NSMutableString stringWithString: @ ""] работает? - PullRequest
7 голосов
/ 01 декабря 2011

Просто интересно:

В NSString есть статический метод, называемый +stringWithString:. Это не переопределено / переопределено в NSMutableString, поэтому мы не можем предполагать, что это вернет NSMutableString. На самом деле, даже в классе NSString тип возвращаемого значения определяется как id и состояния документа :

Возвращаемое значение
Строка, созданная путем копирования символов из aString.

Какую часть цели C мне не хватает в моих знаниях, чтобы понять, почему это работает и возвращает NSMutableString? Тем более, что базовый класс NSString не знает, что мы хотим получить изменяемую строку взамен.

Можно сказать, что внутренне вызывается [Class alloc], который сгенерирует объект типа NSMutableString, но даже это чисто догадки, поскольку у нас нет исходного кода и stringWithString: может делать все, что захочет внутри. 1027 *

Все эти методы класса переопределены в подклассе? И если да, то почему это не задокументировано?

Ответы [ 4 ]

6 голосов
/ 01 декабря 2011

В NSString есть статический метод с именем + stringWithString :.

Более того, это метод класса.

Это не переопределено / не переопределено в NSMutableString

В какао подкласс ненеобходимо переопределить метод.На самом деле, это будет просто производить много шума (IMO).Ему нужно только переопределить метод для предоставления его пользовательской реализации.

, поэтому мы не можем предполагать, что это вернет NSMutableString.

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

Какая частьцели C я пропускаю в своих знаниях, чтобы понять, почему это работает и возвращает NSMutableString?Тем более, что базовый класс NSString не знает, что нам нужна изменяемая строка взамен.

Он «знает», потому что вы написали [NSMutableString stringWithString:@"bah"] вместо [NSString stringWithString:@"bah"].Как и методы экземпляра, методы класса имеют неявное значение self, которое позволяет им передавать тип через методы класса.Поэтому методы класса могут быть переопределены / переопределены по мере необходимости.Методы класса также могут использовать self для определения или сообщения своего типа (пример в ближайшее время).

Можно сказать, что внутренне вызывается [Class alloc], который генерирует объект типа NSMutableString, нодаже это чисто догадки, так как у нас нет исходного кода и stringWithString: он может делать все, что захочет, внутренне.

Это не должно быть догадкой.В этом случае вам следует сообщить об ошибке, если вам была возвращена строка immutable .В противном случае он работает так, как объявлено, независимо от того, использовали ли они одно или несколько определений.

Все эти методы класса переопределены в подклассе?

В случае удобных конструкторов чаще всего используется один из назначенных инициализаторов:

такая реализация может иметь вид:

@implementation NSString
+ (id)stringWithString:(NSString *)arg
{
    // self is either +NSString or +NSMutableString
    return [[[self alloc] initWithString:arg] autorelease];
}

хотя часто можно делать исключения, и часто это происходит с оптимизированными неизменяемыми / изменяемыми типами:

@implementation NSString
+ (id)stringWithString:(NSString *)arg
{
  return [arg imp_isMutable] ? [[[self alloc] initWithString:arg] autorelease] : arg;
}
...
@implementation NSMutableString
+ (id)stringWithString:(NSString *)arg
{
  return [[[self alloc] initWithString:arg] autorelease];
}
...

И если да, то почему это не задокументировано?

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

3 голосов
/ 01 декабря 2011

(что сказал Джастин, но разъяснение)

В NSString есть статический метод с именем + stringWithString :. это не объявлен / переопределен в NSMutableString, поэтому мы не можем предполагать, что это вернет NSMutableString. На самом деле даже в NSString класс возвращаемый тип определяется как id ...

Прежде всего, Objective-C не имеет статических методов . Objective-C имеет методы класса . Методы класса ведут себя точно так же, как методы экземпляра (где класс является экземпляром метакласса) и могут быть унаследованы, переопределены и т. Д. *

Таким образом, точно так же, как NSMutableString наследует characterAtIndex: и может переопределить его для выполнения чего-то особенного, при необходимости NSMutableString может сделать то же самое для методов класса.

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

3 голосов
/ 01 декабря 2011

Вы можете написать инициализатор немного так:

+ (id) stringWithString: (NSString*) foo
{
    return [[self alloc] initWithString:foo];
}

Теперь, когда вы вызываете этот инициализатор на NSString, [self alloc] возвращает NSString, и вы получаете экземпляр NSString обратно. Но когда вы вызываете [NSMutableString stringWithString:@"…"], результат сообщения [self alloc] будет NSMutableString, и, следовательно, инициализатор возвращает изменяемую строку.

3 голосов
/ 01 декабря 2011

NSMutableString является подклассом NSString, поэтому любой метод, вызываемый на NSMutableString, может работать надлежащим образом и возвращать NSMutableString, когда это имеет смысл.Единственный метод, который приходит на ум, который не следует этому, - это copy, который по соглашению возвращает неизменный экземпляр.

Вот почему ваши методы инициализатора возвращают id, а не конкретный экземпляр, и почемувсе методы класса должны использовать [self alloc] вместо [MYActualClass alloc].

...