In ObjC we can use protocols to restrict an id
behavior, so we can declare something like
-(void)aMethod:(id<aProtocol>)aVar
which works very well until we provide a value or a non-id
variable as aVar
, but this gets completely broken since we can pass a generic id
variable delcared without protocols specifiers... Is this normal? Is there any workaround? Am I missing something?
I (FINALLY) found out that using Objective-C++ is the way to go. Let's suppose I want to be able to pass NSString
or NSNumber
(instead of a too much generic id
and instead of using protocols which become useless passing id
values): well, I can create a C++ class having two distinct constructors, one for each ObjC class, so passing id
values cannot be done anymore (almost directly). For example, let's take a look at
class NSStringOrNSNumber{
public:
NSStringOrNSNumber(NSString *);
NSStringOrNSNumber(NSNumber *);
};
The great advantage is that methods/functions taking a NSStringOrNSNumber
parameter can get NSString/NSNumber values DIRECTLY, since the constructor acts as an implicit cast. In other words, if we have
void aFunction(NSStringOrNSNumber param);
the following calls are perfectly valid:
aFunction(@"Hello!");
aFunction(@25);
The only (little) downside is that we need the class to implement a function if we want to get back the value passed to the constructor.
Using a C++ class constructor to get something like id<NSCoding>
is still better the using id<NSCoding>
directly: in fact, if we do the following
@class classOne, classTwo;
class NSCodingClass{
private:
NSCodingClass(classOne *);
NSCodingClass(classTwo *);
public:
NSCodingClass(id<NSCoding>);
}
we won't be able to pass a generic id
as a parameter (since it would be ambiguous: the compiler cannot know which constructor to call among the two private ones)