Creating an abstract class in Objective-C

前端 未结 21 2667
感情败类
感情败类 2020-11-22 15:44

I\'m originally a Java programmer who now works with Objective-C. I\'d like to create an abstract class, but that doesn\'t appear to be possible in Objective-C. Is this poss

21条回答
  •  执笔经年
    2020-11-22 16:14

    If you are used to the compiler catching abstract instantiation violations in other languages, then the Objective-C behavior is disappointing.

    As a late binding language it is clear that Objective-C cannot make static decisions on whether a class truly is abstract or not (you might be adding functions at runtime...), but for typical use cases this seems like a shortcoming. I would prefer the compiler flat-out prevented instantiations of abstract classes instead of throwing an error at runtime.

    Here is a pattern we are using to get this type of static checking using a couple of techniques to hide initializers:

    //
    //  Base.h
    #define UNAVAILABLE __attribute__((unavailable("Default initializer not available.")));
    
    @protocol MyProtocol 
    -(void) dependentFunction;
    @end
    
    @interface Base : NSObject {
        @protected
        __weak id _protocolHelper; // Weak to prevent retain cycles!
    }
    
    - (instancetype) init UNAVAILABLE; // Prevent the user from calling this
    - (void) doStuffUsingDependentFunction;
    @end
    

    //
    //  Base.m
    #import "Base.h"
    
    // We know that Base has a hidden initializer method.
    // Declare it here for readability.
    @interface Base (Private)
    - (instancetype)initFromDerived;
    @end
    
    @implementation Base
    - (instancetype)initFromDerived {
        // It is unlikely that this becomes incorrect, but assert
        // just in case.
        NSAssert(![self isMemberOfClass:[Base class]],
                 @"To be called only from derived classes!");
        self = [super init];
        return self;
    }
    
    - (void) doStuffUsingDependentFunction {
        [_protocolHelper dependentFunction]; // Use it
    }
    @end
    

    //
    //  Derived.h
    #import "Base.h"
    
    @interface Derived : Base
    -(instancetype) initDerived; // We cannot use init here :(
    @end
    

    //
    //  Derived.m
    #import "Derived.h"
    
    // We know that Base has a hidden initializer method.
    // Declare it here.
    @interface Base (Private)
    - (instancetype) initFromDerived;
    @end
    
    // Privately inherit protocol
    @interface Derived () 
    @end
    
    @implementation Derived
    -(instancetype) initDerived {
        self= [super initFromDerived];
        if (self) {
            self->_protocolHelper= self;
        }
        return self;
    }
    
    // Implement the missing function
    -(void)dependentFunction {
    }
    @end
    

提交回复
热议问题