Меня беспокоит странное поведение, проиллюстрированное следующим примером:
NSMutableArray *a1 = [[NSMutableArray alloc] init]; // fine
NSMutableArray *a2 = [NSMutableArray array]; // fine, too
// compiler reports incompatible pointer types; good:
NSMutableArray *a3 = [[NSArray alloc] init];
// compiler says nothing and is happy to assign this!
NSMutableArray *a4 = [NSArray array];
Оба метода init
и array
обоих классов NSArray
и NSMutableArray
возвращают id
. Однако поведение, когда я называю эти методы, просто не то же самое, и clang позволяет мне с радостью назначить пустую переменную NSArray
переменной NSMutableArray
!
Оказывается, что clang автоматически изменяет тип возвращаемого значения некоторых методов, включая семейство init
, на instancetype
и таким образом, во время компиляции можно определить, что [[NSArray alloc] init]
возвращает NSArray *
, а не NSMutableArray *
. Но эта проверка просто не работает с методом array
.
Почему? Должны ли строки, подобные моему последнему примеру, генерировать хотя бы предупреждение? Почему не все эти методы объявлены как возвращающие instancetype
? Будет ли это изменяться в будущем?
Обновление
Хорошие новости: с iOS 7, [NSArray array]
возвращает instancetype
, поэтому присвоение a4
выше также дает предупреждение. Другие методы, такие как arrayWithContentsOfFile:
или arrayWithContentsOfURL
, возвращают id
, хотя...