Search code examples
objective-cprotocolstype-safety

ObjC protocols potentially useless


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?


Solution

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