2010-10-17 4 views
2

У меня есть класс под названием AddressCard из примера в «Программирование в Objective C», и я реализую метод isEqual :.Строгий или свободный ввод при переопределении метода

Сигнатура этого метода в NSObject использует свободный ввод параметра:

- (BOOL)isEqual:(id)anObject 

Ото, образец кода в книге использует строгую типизацию:

- (BOOL) isEqual:(AddressCard *) aCard 

Я не уверен, что я полностью понять, что делает компилятор в этом случае. Я попытался сравнить адресную карту с NSString ([aCard isEqual: @"Foo"]), ожидая либо ошибки времени выполнения (если система использует мой метод), либо что система будет вызывать версию IsEqual от NSObject.

Вместо этого мой метод был вызван (даже если параметр был NSString и не AddressCard) и вызывает исключение, когда мой IsEqual: попытался вызвать аа метод, специфичный к AddressCard:

- (BOOL) isEqual:(AddressCard *) aCard { 
    if ([name isEqualToString: [aCard name]] && /*here I get the error*/ 
     [email isEqualToString:[aCard email]]) { 
     return YES; 
    }else { 
     return NO; 
    } 
} 

Что происходит ? Как на Земле NSString передается методу, который ожидает что-то еще? Меняет ли подпись метод OK при его переопределении?

ответ

1

Время выполнения отличает сообщения от их селектора. Все методы с тем же именем имеют один и тот же селектор. Параметры метода не влияют на селектор. В вашем случае селектор isEqual:.

Это от Apple «Объективный-C Язык программирования» (курсив мой):

распорядке сообщений имеет доступ к реализации метода только через селекторы, поэтому он рассматривает все методы с тем же селектором, так. Он обнаруживает тип возврата метода и типы данных его аргументов из селектора. Поэтому, за исключением сообщений, отправленных статически типизированным приемникам, динамическое связывание требует, чтобы все реализации одинаково названных методов имели одинаковый тип возврата и те же типы аргументов. (Статический типизированные приемники являются исключением из этого правила, так как компилятор может узнать о реализации методы от типа класса.)

Других слов: изменение подписи существующего метода не является хорошей формой (IMO), но это нормально, если вы статически вводите приемники этих методов (в вашем случае это означает, что aCard должен быть объявлен как AddressCard *). Для среды исполнения это не проблема.

К сожалению, вы не упомянули, дает ли компилятор предупреждение, потому что вы передаете NSString *, где он ожидает AddressCard *. Я бы ожидал, что он это сделает.

+0

Предупреждение отсутствует. Это просто вызывает исключение во время выполнения. – cfischer

+0

Я бы тоже ожидал предупреждения. Кажется немного неаккуратным ... – cfischer

+0

BTW, если я меняю подпись своего метода isEqual:, так что он соответствует NSObject, я получаю предупреждение: «Conflicting types for» - (BOOL) isEqual: (id *) aCard. ? O :-) – cfischer

1

Мое лучшее предположение: весь компилятор видит метод, который ожидает, что указатель будет вызван с параметром указателя. Нет проблем для компилятора.

 Смежные вопросы

  • Нет связанных вопросов^_^