Jeremy W. Sherman
Jeremy W. Sherman

Reputation: 36143

Two class methods, same name, different signatures: How to force compiler to use intended one?

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>

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 is bad in that it won't help anyone else who wants to call the method.

Upvotes: 5

Views: 2089

Answers (3)

Dave DeLong
Dave DeLong

Reputation: 243156

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).

Upvotes: 2

Joshua Weinberg
Joshua Weinberg

Reputation: 28688

Just do [(MyClass*)[self class] port]. This will work in all cases and is the simplest way.

Upvotes: 0

al45tair
al45tair

Reputation: 4433

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.

Upvotes: 4

Related Questions