How do I force the compiler to select the desired method from a set of class methods sharing the same name?
/* Use +[MyClass port](UInt16 (*)(id, SEL),
* not +[NSPort port](NSPort *(*)(id, SEL)). */
UInt16 port = [[self class] port];
I have an Objective-C class with a class method:
+ (UInt16)port;
NSPort
has a convenience constructor whose signature conflicts with this:
+ (NSPort *)port;
Sending +port
to my class results in a compiler warning:
UInt16 port = [[self class] port];
W: Multiple methods named '+port' found
W: Using '+(NSPort *)port'
W: Also found '+(UInt16)port'
Fail: The compiler has chosen the wrong method signature.
Type inference fail: Using [[(MyClass *)self class] port]
does not cadge it into using the right method.
ETA: Here is the workaround I am using for now:
#import <objc/runtime.h>开发者_如何学C
Class c = [self class];
SEL s = @selector(port);
typedef UInt16 (*PortIMP)(id, SEL);
PortIMP MyClassGetPort = (PortIMP)class_getMethodImplementation(c, s);
UInt16 port = MyClassGetPort(c, s);
It is good in that:
- It handles dispatching to any subclass implementation correctly.
- It is confined to the implementation file, so this ugliness is not inflicted on anyone but the implementer.
It is bad in that it won't help anyone else who wants to call the method.
Interesting… there doesn’t seem to be an obvious solution to this one.
You could use a protocol to declare the methods you need, for instance
@protocol MyClassProtocol
@optional
- (UInt16)port;
@end
then do
UInt16 port = [(id <MyClassProtocol>)[self class] port];
Not pretty, but it does work.
Why not just rename the method? (lame, I know) You could argue that a method named "port" should be returning a port object (which is what NSPort
does), and that if you wanted to return a primitive "port number", you'd call it "portValue" (a la "intValue", "longLongValue", etc).
Just do [(MyClass*)[self class] port]
. This will work in all cases and is the simplest way.
精彩评论