I'm doing some code refactoring but facing a problem that clang has no any warning for this situation:
@protocol CommonProtocol <NSObject>
- (void)common;
@end
=========
@interface Foo : NSObject <CommonProtocol>
- (void)foo;
@end
=========
@interface Bar : NSObject <CommonProtocol>
@end
=========
static id<CommonProtocol> getObject(void) {
return [Bar new];
}
Foo *casting = getObject(); /// ⚠️ there is no warning for this
[casting common];
[casting foo]; /// 💥 crash because the casting object do not respond to '-foo'
I think type 'Foo *' and 'id<CommondProtocol>' are not interchangeable and looking a way to promote this warning. Any compile flag to achieve this?
NOTE: I have try '-Weverything' and it still present no warning for conversion.
This is a natural consequence of the weak type system of Objective-C, where id
can be virtually downcasted to any kind of object. Specializing id
with a given protocol doesn't help much in this direction, this is why you can easily run into unexpected situations, like the current one.
If you want to force the casting, one solution would be to change the signature of getObject
to return NSObject
instead of id
:
static NSObject<CommonProtocol> *getObject(void) {
return [Bar new];
}
With this setup in place the naive Foo *casting = getObject();
will generate a clear warning:
Incompatible pointer types initializing 'Foo *' with an expression of type 'NSObject *'
, and the person writing the code will have to explicitly cast:
Foo *casting = (Foo *)getObject();