Ответ 1
Подклассы могут изменять типы, связанные с методами. В общем случае подкласс может специализировать тип возвращаемого значения и может сделать типы аргументов более универсальными. На самом деле это имя, но я не могу вспомнить, что это такое. Во всяком случае, здесь рациональное:
Типы возврата
Если у меня есть класс
@interface A
- (id)foo;
@end
и еще один класс
@interface B : A
- (NSString *)foo;
@end
И у меня есть экземпляр B* b
, я могу отбросить его до A*
и по-прежнему соответствовать сигнатуре типа метода -[A foo]
, потому что любой NSString*
также является id
.
Однако я не могу сделать это более обобщенным. Если вместо этого у меня есть
@interface A
- (NSString *)foo;
@end
@interface B : A
- (id)foo;
@end
И у меня есть экземпляр B* b
, и я отбрасываю его на A*
, тогда тип [(A*)b foo]
равен NSString *
, и все же фактическое значение может быть любым id
, потому что указанный тип я -[B foo]
. Это нарушение системы типов.
Аргументы
Если у меня есть класс
@interface A
- (void)foo:(NSString *)obj;
@end
и еще один класс
@interface B : A
- (void)foo:(id)obj;
@end
И у меня есть экземпляр B* b
, и я отбросил его до A*
, тогда любой действительный аргумент [(A*)b foo:obj]
также соответствует типу -[B foo:]
, потому что любой NSString *
также является id
.
Однако, если у меня есть следующий
@interface A
- (void)foo:(id)obj;
@end
@interface B : A
- (void)foo:(NSString *)obj;
@end
И у меня есть экземпляр B* b
, и я отбросил его до A*
, тогда я мог бы передать любой id
в [(A*)b foo:obj]
, но базовый класс B
ожидает только NSString*
s. И таким образом я нарушил систему типов.
Свойства
Вот клеймо. Когда вы объявляете тип свойства, вы объявляете как возвращаемый тип getter, так и тип аргумента setter. Согласно приведенным выше правилам это означает, что вы не можете изменить тип свойства, потому что в одном из двух случаев вы будете нарушать систему типов.
Выше была теория. На практике я понятия не имею, если GCC или Clang применяют эти ограничения. Возможно, они предполагают, что программист знает лучше всего, и ненадлежащим образом обобщая или специализируя тип, будет тихо нарушать систему типов за вашей спиной. Вам придется экспериментировать. Но если компилятор действительно прав, он будет запрещать обобщение возвращаемых типов и специализированных аргументов. И это означает, что он запретит изменение типа свойства.
Даже если компилятор разрешает это, вы, вероятно, не должны этого делать. Тихая разбивка системы типов - отличный способ ввести ошибки и показатель плохой архитектуры.