Использование Objective-C Introspection против принудительного переопределения дополнительного сообщения? - PullRequest
1 голос
/ 17 января 2012

У меня есть базовый класс, который добавляет некоторые функциональные возможности для ряда производных классов в моем приложении.

Одна из этих функций используется только некоторыми подклассами.

В настоящее время я использую метод, который возвращает BOOL, по умолчанию NO для «короткого замыкания» этой функции.Подклассы, которым требуется эта функция, должны переопределить этот метод и вернуть YES.

Эта функция полезна, только если вы также переопределили хотя бы один из двух других методов.

Я бы предпочелиспользовать class_copyMethodList, чтобы определить, реализовал ли подкласс один из этих двух методов (вместо использования метода, который возвращает BOOL).

О каких препятствиях / препятствиях / недостатках такого подхода я должен знать?Существует ли стандартная реализация этой идиомы, которую я могу использовать?

Ответы [ 2 ]

2 голосов
/ 17 января 2012

Если я могу предложить альтернативный подход, рассматривали ли вы вопрос об использовании -instanceMethodForSelector в соответствующем экземпляре подкласса и сравнении с результатом в базовом классе?

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

РЕДАКТИРОВАТЬ: как обсуждено в комментариях ниже, еще одна альтернатива - объявить формальный протокол, что подчиненныйклассы могут реализовать и использовать NSObject -conformsToProtocol: для определения того, реализован ли протокол.Так как conformsToProtocol возвращает, объявил ли класс поддержку протокола (в его @interface через синтаксис угловых скобок), это очень похоже на добавление пользовательского метода BOOL, который по умолчанию возвращает NO, но без синтаксического исемантические накладные расходы по принятию собственного специального решения.

1 голос
/ 17 января 2012

У меня есть базовый класс, который добавляет некоторые функциональные возможности к ряду производных классов в моем приложении.

Это предложение должно заставить вас переосмыслить свой дизайн. Базовый класс никогда не должен ничего делать с производными классами. Он должен не знать своих подклассов. (Несмотря на классовые кластеры. Это отдельный подход к проектированию, требующий, чтобы суперкласс был осведомлен о построении, что делает его шаблоном Factory, что хорошо.)

Одна из этих функций используется только некоторыми подклассами.

Это явный признак ошибки "Квадрат / Прямоугольник". В ООП (забудьте ObjC, это просто теория CS), квадрат не является прямоугольником . Вы должны убедиться, что ваши типы соответствуют принципу замещения Лискова. Опять же, это не имеет никакого отношения к какому-либо конкретному языку; это верно для всего дизайна ООП. Это может показаться очень «теоретическим», но оно серьезно испортит вашу реализацию, если вы выйдете из строя LSP, и вы будете преследовать тонкие ошибки гораздо дольше, чем вам нравится.

Шаблон, который вам, вероятно, нужен здесь, это Decorator, а не подклассы. Если у вас есть некоторые специальные функции, которые существуют в некоторых классах, вы хотите инкапсулировать эти функции в отдельный объект и присоединить его к подклассам, где это имеет смысл. Другим возможным шаблоном является Стратегия (которая обычно реализуется как «делегат» в ObjC, что является другим способом мышления о Decorator). Дело в том, что вам не нужна логика в суперклассе, которая применима только к некоторым подклассам. Вы хотите поместить эту логику в то, что существует только в соответствующих подклассах.

Если вам все это не поможет, тогда я настоятельно рекомендую простую функцию (BOOL) для всего, что анализирует реализации метода. Этот способ хрупок, потому что он опирается на все более глубокие детали реализации. respondsToSelector: определенно лучше, чем тестирование instanceMethodForSelector:.

...