Вопрос по objective-c, ios – Узкий тип имущества в подклассе

4

Сегодня я столкнулся со странным поведением, которое я не ожидал, что компилятор Objective-C позволит.

В UITableViewCell есть свойство с именем imageView типа UIImageView. Я подкласс UITableViewCell и перезаписал imageView, за исключением того, что я сделал его типа AWImageView, где AWImageView является подклассом UIImageView. Я думал, что это не скомпилируется, но это так. Все работает просто отлично. Я был очень шокирован поведением.

Разрешено ли официально сужение типа имущества в подклассе? Или это ошибка в компиляторе Objective-C, которая заставила его работать?

Ваш Ответ

2   ответа
5

что ему разрешено это делать, вполне обосновано, но в этомparticular если ты в порядке ...

В строгой подтиповой интерпретации переопределения переопределяющий метод может принимать аргументы более общего типа и возвращать значение более специфического типа.

Например, используя Objective-C, учитывая:

@interface A : NSObject { ... }
@interface B : A { ... }
@interface C : B { ... }

и метод М в Б:

- (B *) M:(B *)arg { ... }

тогда в классе C под строгим подтипом это можно переопределить в классе C, используя:

- (C *) M:(A *)arg { ... }

Это безопасно, потому что если у вас есть ссылка на явно B-объект:

B *bObj = ...;

а затем метод М называется:

B *anotherBObj = [bObj M:[B new]];

то лиbObj на самом деле это B или C, вызов является корректным типом - если это объект C, то аргумент, являющийся B, подходит, так как он также является A, и результат, являющийся C, является прекрасным, поскольку он также является B ,

Что приводит нас кnot quite, ваша собственность; в Objective-C свойство - это просто сокращение для двух методов:

@property B *myBvalue;

является сокращением для:

- (void) setMyBvalue:(B *)value;
- (B *) myBvalue;

Если это свойство объявлено в B, а вы переопределяете его в классе C с помощью C-значного свойства:

@property C *myBvalue;

ты получаешь:

- (void) setMyBvalue:(C *)value;
- (C *) myBvalue;

и методsetMyBvalue: нарушает строгое правило подтипирования - приведение экземпляра C к экземпляру B, а правила набора говорят, что вы можете передать B, метод ожидает C, и может возникнуть хаос.

However в вашем случае собственность, которую вы переопределяете,readonlyтак что нет сеттера и нет опасности.

1

то это UIImageView, поэтому для компилятора все остается одинаковым.

из документов:

enter link description here http://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjectiveC/Art/graphichierarchy.gif
Figure 1-1 […] This is simply to say that an object of type Square isn’t only a square, it’s also a rectangle, a shape, a graphic, and an object of type NSObject.

Знаете ли вы какие-либо документы, подтверждающие это? Я почти уверен, что Objective-C не допустил этого раньше. - (id) init возвращает id, потому что он не позволял подклассу переопределять метод и возвращать более узкий тип. Evil Nodoer
Хорошая цитата из документов, но просто хотел бы отметить, что изображение в вашей цитате является неработающей ссылкой.
это очень нормальное поведение в любом объектно-ориентированном языке, основанном на классах, который поддерживает наследование. подкласс может рассматриваться как родительский класс. и вы ошиблись с init: он указывает id, так что любой подкласс может вернуть объект самого себя (или [см. кластер классов] другой класс, который будет действовать аналогично).

Похожие вопросы