Specific Class type parameter in Objective-C

后端 未结 4 1418
[愿得一人]
[愿得一人] 2021-02-13 18:22

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 use

相关标签:
4条回答
  • 2021-02-13 18:53

    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;
    
    0 讨论(0)
  • 2021-02-13 18:55

    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**.

    0 讨论(0)
  • 2021-02-13 19:03

    If you want to init dealership with a vehicle (I mean an initialized instance) you should do:

    - (id)initWithCar:(Vehicle *)carClass
    {
        //An extra check (only for DEBUG mode)
        NSAssert([carClass isKindOfClass:[Vehicle class]]);
        ... //carClass is now a Vehicle instance
    }
    
    0 讨论(0)
  • 2021-02-13 19:15

    I'm not sure exactly what kind of solution you're getting at, but perhaps treating Vehicle as a class cluster would enable you to coalesce the common functionality under one umbrella, and have the class cluster manage the different implementations (and mask them from the user)?

    For example, NSString does this; underlying instances are usually of type NSCFString, unless they're literals (i.e. @"this is a literal, in code"), in which case they are NSConstantStrings.

    Here is an excerpt from a relevant blog post explaining class clusters:

    In a nutshell, it’s a design that allows you to incorporate a family of functionally-related of objects into your application while keeping the code interacting with those objects loosely coupled, flexible, and easy to maintain or update.

    A class cluster conforms this set of common objects to behave according to a single interface and, furthermore, channels all creation of them through that interface. The construction is made up of two key parts: a) one public, abstract interface serving as the “face” of the cluster which advertises the supported API, and b) many private, concrete subclasses of this interface responsible for actually implementing the advertised behavior of the superclass in their own specific way. The abstract superclass does implement a few methods itself, the most significant being a factory method to vend instances of the private subclasses; other common functionality shared across all subclasses, such as accessors, can also be defined here and shared as well.

    Users of the cluster only ever see the one public superclass, are unaware that it is actually abstract, and know nothing about the existence of any private concrete subclasses. The superclass offers a factory creational method which is responsible for determining which subclass is appropriate for any given situation and transparently returning an instance of it. Since this returned object implements and behaves according to the public superclass’ interface, users can simply assume they have obtained a direct instance of this superclass.

    0 讨论(0)
提交回复
热议问题