Objective c protocol generics
Asked Answered
G

4

10

Can Objective-C protocol be generic?

Following this tutorial, I'm basically looking for something like that:

@protocol ItemsStore<__covariant ObjectType> <NSObject>

-(NSArray <ObjectType> *)items;

@end

Which is a generic protocol for some ObjectType that "implements" ("inherits") another protocol NSObject

Giblets answered 3/2, 2016 at 17:10 Comment(3)
FYI - #35143694Hippocrene
How on earth did that not come up on my search. ThanksGiblets
I don't think it makes sense. Marking a class as a generic covariant allows an instance of that class to qualify for the generic. However if you put it in a protocol the compiler doesn't know what you're intending to do.Mantelet
G
4

As @rmaddy suggested, and as referred to this questions, it is NOT possible. Shame, moving to Swift then...

Giblets answered 11/7, 2016 at 8:19 Comment(0)
S
1

Maybe you could just redefine it as generic in the interface.

@protocol ItemsStore <NSObject>

- (NSArray *)items;

@end

@interface MyItemsStore<ObjectType> : NSObject <ItemsStore>

- (NSArray <ObjectType> *)items;

@end

This seems an unlikely scenario though. You might be better just defining the type of the items in each subclass. Like what Apple do with NSFetchRequest in their core data model generation.

Sprit answered 31/10, 2017 at 21:39 Comment(1)
just the syntax I was looking for. Can't have enough of 'em. Angle brackets.Barracuda
F
0

Probably, this question has exactly the same source problem as mine. Well, the idea of the design is great but doesn't work with ObjC. I also was wondering about that. I thought it could work some way like that:

@protocol Prototype<__covariant OtherProtocolOrClass> <NSObject>
/// Construct an object of the desired class or protocol
@property (nonatomic, nonnull, readonly) <OtherProtocolOrClass> objectFromPrototype;
@end

(I have not tested @protocol Prototype <NSObject,__covariant OtherProtocolOrClass> yet, but think it will fail.)

Another object in my framework (it is a collection) states, it can auto-construct an NSArray<ObjectType>* of an object type, if there is a Prototype that returns instances, like this:

@interface ValueProto : NSObject <Prototype<id<Value>>>
@end

@implementation ValueProto
-(id<Value>)objectFromPrototype {
    return [Value new];
}
@end

Im my dreams, the collection was constructed like this:

MyCollection<id<Value>>* const collection = [MyCollection new];
collection.prototype = [ValuesProto new];

And if you then access the collection's property, your array of id<Value> objects is constructed on the fly:

-(NSArray<id<Value>>*)values {
    NSArray*const sourceCollection = ...
    NSMutableArray<id<Value>>* const result = [NSMutableArray arrayWithCapacity:sourceCollection.count];
    for (id o in sourceCollection) {
        id<Value> v = self.prototype.objectFromPrototype;
        v.content = o;
        [result addObject:v];
    }
    return result;
}

Instead one of my class' objects must be the prototype itself:

-(id)objectFromPrototype {
    return [self.class new];
}

That clashes with my so-called 'Injector', which constructs and returns objects by protocols instead of classes.

If any Apple engineer is reading this:

Please, provide protocol covariants for ObjC. It's not yet dead! :-)

Faus answered 1/12, 2020 at 13:24 Comment(0)
M
0

Why not use generic abstract class?

@interface AbstractItemStore <__covariant ObjectType> : NSObject

- (NSArray<ObjectType> *)items;

@end

@implementation AbstractItemStore

- (NSArray<id> *)items {
    NSParameterAssert("Not implemented!");
    return nil;
}

@end
Muzzleloader answered 1/4, 2021 at 2:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.