Подклассы могут изменять типы, связанные с методами.В общем, подкласс может специализировать возвращаемый тип и может сделать типы аргументов более общими.На самом деле есть имя для этого, но я не могу вспомнить, что это такое.Во всяком случае, вот рациональное:
Типы возврата
Если у меня есть класс
@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*
с.И, таким образом, я нарушил систему типов.
Свойства
Вот точка соприкосновения.Когда вы объявляете тип свойства, вы объявляете оба типа возвращаемого значения получателя и тип аргумента установщика.Согласно приведенным выше правилам, это означает, что вы не можете изменить тип свойства, потому что в одном из двух случаев вы нарушите систему типов.
Выше приведена теория.На практике я понятия не имею, применяют ли GCC или Clang эти ограничения.Возможно, они предполагают, что программист знает лучше, а неправильное обобщение или специализация типа молча сломает систему типов за вашей спиной.Вам придется экспериментировать.Но если компилятор действительно корректен, он не разрешает обобщать возвращаемые типы и специализировать аргументы.А это значит, что это не позволит изменять тип свойства.
Даже если компилятор это позволяет, вам, вероятно, не следует этого делать.Безмолвное разрушение системы типов - это отличный способ выявить ошибки и показатель плохой архитектуры.