В интерфейсе подклассов я объявляю метод, реализованный суперклассом, как возвращающий другой тип объекта, поскольку подкласс является специализированным. Однако мне не нужно реализовывать метод в подклассе - реализация суперкласса работает нормально. К сожалению, этот шаблон теперь, кажется, дает мне Method definition for … not found error
в последних версиях XCode.
Я знаю, что могу отключить все таких предупреждений, отключив -Wincomplete-implementation
с diagnostic push
и pop
вокруг @implementation
, но я бы Скорее не принимайте такой крайний подход, так как предупреждение полезно в других контекстах. (Если это может пометить отдельные методы, чтобы замолчать, я все уши)
Вот одна из нескольких примеров реализации, которые демонстрируют эту проблему:
test.h
@interface GeneralItem : NSObject
@end
@interface GeneralGroup : NSObject
- (GeneralItem *)item;
@end
@interface ItemA : GeneralItem
@end
@interface GroupA : GeneralGroup
- (ItemA *)item;
@end
Test.m
#import "Test.h"
@implementation GeneralGroup
- (GeneralItem *)item
{
return nil;
}
@end
@implementation GroupA
// Warning: Method definition for 'item' not found
@end
Чтобы было ясно, все компилируется и работает нормально, и, насколько я понимаю, компилятор должен знать, что суперкласс реализует этот метод, не говоря уже о том, что Objective-C не слишком требователен к перегрузке типов в определениях методов.
Я бы хотел избежать реализации метода и простого вызова super
, так как я считаю его полностью избыточным кодом, но если кто-то может подтвердить мне, что компилятор оптимизирует прямой вызов super
, так что среда выполнения может делать свое обычное дело без необходимости делать пит-стоп для подкласса, и это единственный способ заставить замолчать это предупреждение, пусть будет так.
<ч />
Редактировать 1
Вот несколько других сценариев, в которых это происходит.
Первый - это сценарий, в котором общий базовый класс (или абстрактный суперкласс) реализует совместную реализацию чего-либо, скажем, с блоками, но мы хотим, чтобы только некоторые подклассы выборочно объявляли свою поддержку для него с должным образом аннотируемыми типами:
BlockTest.h
@interface GeneralItem : NSObject
@end
@interface GeneralGroup : NSObject
@end
@interface ItemA : GeneralItem
@end
@interface GroupA : GeneralGroup
- (void)loadItemWithCompletionHandler:(void (^)(ItemA *item))completionHandler;
@end
@interface ItemB : GeneralItem
@end
@interface GroupB : GeneralGroup
- (void)loadItemWithCompletionHandler:(void (^)(ItemB *item))completionHandler;
@end
BlockTest.m
#import "BlockTest.h"
@interface GeneralGroup ()
- (id)item;
- (void)loadItemWithCompletionHandler:(void (^)(Item *item))completionHandler;
@end
@implementation GeneralGroup
- (void)loadItemWithCompletionHandler:(void (^)(Item *item))completionHandler;
{
if (completionHandler) completionHandler(self.item);
}
@end
@implementation GroupA
// Warning: Method definition for 'loadItemWithCompletionHandler:' not found
// A custom implementation of -item can be here, for instance
@end
Следует отметить, что вы не получите предупреждения, если вы объявите метод как - (void)loadItemWithCompletionHandler:(void (^)(Item *item))completionHandler;
в общедоступном заголовке в GroupA
, но вы do получите предупреждение "определение метода не найдено" при изменении тип, который будет подклассом первоначально указанного типа.
<ч />
Во-вторых, вы просто хотите дать больше контекста методу, предоставленному суперклассом (используя NSObject
copy
здесь, но это относится к любому методу, типизированному как id
, который мы хотели бы повторно объявляйте с более точными типами, чтобы такие вещи, как связывание свойств, работали менее безболезненно
Subclass.h
@interface Subclass : NSObject
- (instancetype)copy;
@end
Subclass.m
#import "Subclass.h"
@implementation Subclass
// Warning: Method definition for 'copy' not found
@end