Skip to content

Instantly share code, notes, and snippets.

@douglashill
Last active November 25, 2016 14:53
Show Gist options
  • Save douglashill/802ed825389cc5de6e9d to your computer and use it in GitHub Desktop.
Save douglashill/802ed825389cc5de6e9d to your computer and use it in GitHub Desktop.
A quick look at variance with Objective-C generics. `NSSet` is covariant on its `ObjectType`, while `NSHashTable` is invariant. Contravariance is also supported.
@import Foundation;
@interface ContravariantCollection<__contravariant ObjectType> : NSObject
@end
@implementation ContravariantCollection
@end
void stringSetThing(NSSet<NSString *> *set) {
}
void mutableStringSetThing(NSSet<NSMutableString *> *set) {
}
void stringHashTableThing(NSHashTable<NSString *> *hashTable) {
}
void mutableStringHashTableThing(NSHashTable<NSMutableString *> *hashTable) {
}
void stringContraThing(ContravariantCollection<NSString *> *set) {
}
void mutableStringContraThing(ContravariantCollection<NSMutableString *> *set) {
}
int main(int argc, char *argv[]) {
@autoreleasepool {
NSSet<NSString *> *setOfStrings;
NSSet<NSMutableString *> *setOfMutableStrings;
stringSetThing(setOfStrings);
stringSetThing(setOfMutableStrings); // Okay, because NSSet<NSMutableString *> is a subtype of NSSet<NSString *>
mutableStringSetThing(setOfStrings); // Warning: Incompatible pointer types passing 'NSSet<NSString *> *' to parameter of type 'NSSet<NSMutableString *> *'
mutableStringSetThing(setOfMutableStrings);
NSHashTable<NSString *> *tableOfStrings;
NSHashTable<NSMutableString *> *tableOfMutableStrings;
stringHashTableThing(tableOfStrings);
stringHashTableThing(tableOfMutableStrings); // Warning: Incompatible pointer types passing 'NSHashTable<NSMutableString *> *' to parameter of type 'NSHashTable<NSString *> *'
mutableStringHashTableThing(tableOfStrings); // Warning: Incompatible pointer types passing 'NSHashTable<NSString *> *' to parameter of type 'NSHashTable<NSMutableString *> *'
mutableStringHashTableThing(tableOfMutableStrings);
ContravariantCollection<NSString *> *collectionOfStrings;
ContravariantCollection<NSMutableString *> *collectionOfMutableStrings;
stringContraThing(collectionOfStrings);
stringContraThing(collectionOfMutableStrings); // Warning: Incompatible pointer types passing 'ContravariantCollection<NSMutableString *> *' to parameter of type 'ContravariantCollection<NSString *> *'
mutableStringContraThing(collectionOfStrings); // Okay, because MyCollection<NSString *> is a subtype of MyCollection<NSMutableString *>
mutableStringContraThing(collectionOfMutableStrings);
}
return 0;
}
@douglashill
Copy link
Author

@douglashill
Copy link
Author

bob’s comment about variance on this Objective C Generics article clearly explains why Apple’s immutable collections are covariant, and their mutable collections are invariant.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment