Class cluster with clang: how to use `__attribute__((objc_method_family(none)))`?

1.1k Views Asked by At

I want to implement a class cluster (with ARC), but clang gets in the way. Here is one init method that returns a concrete instance of another class - which is the point of class clusters:

@implementation PlaceholderServer
- (Server *) init {
    MockServer *concreteServer = [[MockServer alloc] init];
    return concreteServer;
}
@end

And clang complains on the return statement:

warning: incompatible pointer types returning 'MockServer *__strong' from a function with result type 'PlaceholderServer *' [-Wincompatible-pointer-types]

I understand the reason for that warning: init is recognized by clang as belonging to the init family of methods which are supposed to return instances of the implementing class (or perhaps a subclass). That's typically not the case in a class cluster where the actual concrete class to instantiate can vary depending on whatever condition.

clang provides an annotation to override the automatic recognition of method families: __attribute__((objc_method_family(FAMILLY))), where familly can be one of alloc, copy, init, mutableCopy, or new. It can also be none, about which the documentation says: "If family is none, the method has no family, even if it would otherwise be considered to have one based on its selector and type."

Unfortunately, I can't manage to make it work in my case. If I add the following declaration to the @interface:

- (SGIServer *) init __attribute__((objc_method_family(none)));

Then the warning doesn't go away. If I add the attribute to the implementation:

- (Server *) init __attribute__((objc_method_family(none)))
{
    MockServer *concreteServer = [[MockServer alloc] init];
    return concreteServer;
}

Then the warning doesn't go away and I also get an error:

error: method was declared as an 'init' method, but its implementation doesn't match because its result type is unrelated to its receiver type
- (SGIServer *) init __attribute__((objc_method_family(none)))
^

And if I do both, the initial warning doesn't go away, but I get an additional warning:

warning: attributes on method implementation and its declaration must match [-Wmismatched-method-attributes]

So I suppose I am missing something elementary, but what?

This is with Xcode 4.3.2 or Xcode 4.4DP2.

1

There are 1 best solutions below

0
On

No messing with attributes should be necessary; you should be able to instead return (id) concreteServer;, which switches to dynamic typing.