I want to accept a Class object as a parameter to a constructor of one of my classes. It needs to do a lot of custom work with it, and I want to abstract that away from the user of the class.
For example, let's say my class is a Dealership and I want to initialize it with any type of Vehicle.
So I have the following hierarchy:
Dealership : NSObject
Vehicle : NSObject
Truck : Vehicle
Van : Vehicle
Car : Vehicle
What I want to do is, inside Dealership, implement the following initializer:
- (id)initWithVehicle:(Class)aVehicle;
Except instead of accepting a generic Class, I'd like to restrict it to only Classes of type "Vehicle" (which would include all my inherited classes). I could just test for this property in the initializer, but it would be great if there was a way to enforce this at compile time instead of waiting for runtime feedback.
It seems you can reference Class to restrict to classes that implement a certain interface, so I could do some hackery there. Is there any way to refer to Class objects of a specific type though?
EDIT - Note that I edited the example classes because the original example was a bit misleading. The example is just for demonstration purposes, not the actual class hierarchy I'm working with.
You can ensure using a protocol check:
- (id)initWithVehicle:(id<VehicleProtocol>)aVehicle;
...
}
Declaring an object as id tells the compiler that you don't care what type the object is, but you do care that it conforms to the specified VehicleProtocol protocol**.
Not at compile-time, but you can release self
and return nil
if the class is invalid:
- (id)initWithCar: (Class)carClass {
self = [super init];
if (self) {
if (![carClass isSubclassOfClass:[Car class]]) {
[self release];
self = nil;
} else {
// Normal initialization here.
}
}
return self;
}
That's the closest you'll get to the sort of restriction you want.
But this sort of design suggests you need to rethink your class hierarchy. Rather than passing a subclass of Car
, you should have a Manufacturer
class. Something like this:
@interface Manufacturer : NSObject
+ (id)manufacturerWithName: (NSString *)name;
- (NSArray *)allCars;
@property (readonly) Car *bestsellingCar;
// etc.
@end
#define kManufacturerVolvo [Manufacturer manufacturerWithName: @"Volvo"]
#define kManufacturerToyota [Manufacturer manufacturerWithName: @"Toyota"]
// etc.
And then this initializer for Dealership:
- (id)initWithManufacturer: (Manufacturer *)aManufacturer;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With