防止类在Objective-c中被子类化

时间:2013-10-05 06:36:47

标签: objective-c

如何防止特定类被子类化? 我不知道该语言中的此类功能(例如final关键字)。然而,Apple表示它已经为AddressBookUI.framework(在iOS中)的所有类完成了这项工作

出于教育目的,我如何实现相同的功能,或者他们将如何做到这一点?

来自iOS7 Release Notes(Requires login)

enter image description here

4 个答案:

答案 0 :(得分:12)

以下是一种方法:在“最终”类中覆盖allocWithZone:(用MyFinalClassName代替您的实际类名),如下所示:

+ (id)allocWithZone:(struct _NSZone *)zone
{
    if (self != [MyFinalClassName class]) {
        NSAssert(nil, @"Subclassing MyFinalClassName not allowed.");
        return nil;
    }

    return [super allocWithZone:zone];
}

这将阻止不属于MyFinalClassName成员的子类被alloc'编辑(因此也init',因为NSObject的最终必须调用allocWithZone:,并且拒绝从“最终”类中调用super,您将阻止此操作。

答案 1 :(得分:6)

作为Swift互操作的结果,有一种更简单的方法来防止Xcode 6中的子类化。为了防止Swift类在Objective-C中被子类化,objc_subclassing_restricted被添加到{ProjectName}-Swift.h文件中的所有类定义。

您可以在项目中使用它:

#if defined(__has_attribute) && __has_attribute(objc_subclassing_restricted)
# define FOO_FINAL __attribute__((objc_subclassing_restricted))
#else
# define FOO_FINAL
#endif

FOO_FINAL
@interface Foo : NSObject
@end

@interface Bar : Foo
@end

编译器将停止Bar的定义,其中不能使用objc_subclassing_restricted属性

对类进行子类化

答案 2 :(得分:2)

这是可能的解决方案:

@interface FinalClass : NSObject

@end

@implementation FinalClass

- (id)init
{
    if (self.class != [FinalClass class]) {
        return nil;
    }
    self = [super init];
    if (self) {
        // instance initialization
    }
    return self;
}

@end

@interface InvalidSubclass : FinalClass

@end

@implementation InvalidSubclass

- (id)init
{
    self = [super init];
    if (self) {

    }
    return self;
}

@end

我不确定这是100%保证,因为无论如何它都是运行时检查,但它应该足以阻止并警告人们不应该将其子类化。子类可能会跳过超类的init,但实例将无法使用,因为它没有被超类完全初始化。

答案 3 :(得分:0)

以下内容将确保每次“不可能的子类”调用+alloc时,将分配一个对象,该对象是FinalClass的实例,而不是子类。这本质上是NSObject的+alloc方法所做的,但在这里我们指定一个要创建的显式类。这是NSObject allocates instances (in Obj-C 2)的方式,但无法保证始终如此,因此您可能需要添加一个调用-dealloc的相应object_dispose。如果您尝试实例化子类,此方法还意味着您不会获得nil对象 - 您确实获得了FinalClass的实例。

@interface FinalClass: NSObject
//...
+ (id)alloc; // Optional
@end

// ...

#import <objc/runtime.h>
@implementation FinalClass

+ (id)alloc {

    if (![self isMemberOfClass:[FinalClass class]]) {
        // Emit warning about invalid subclass being ignored.
    }

    self = class_createInstance([FinalClass class], 0);
    if (self == nil) {
        // Error handling
    }
    return self;
}

@end

@interface InvalidSubclass : FinalClass
// Anything not in FinalClass will not work as +alloc will
// create a FinalClass instance.
@end

注意:我不确定自己是否会使用它 - 指定不应将类子类化为与程序员签订设计合同的本质,而不是编译或运行时强制规则。