How do I prevent a particular class from being subclassed?
I am not aware of such functionality (say final
keyword for example) in the language. However Apple says it has done so for all classes in AddressBookUI.framework (in iOS)
For educational purposes, how can I achieve the same functionality, or how would they have done such thing?
From iOS7 Release Notes(Requires login) :
Here's one way: override allocWithZone:
from within your "final" class (substituting MyFinalClassName
for your actual class name) like this:
+ (id)allocWithZone:(struct _NSZone *)zone
{
if (self != [MyFinalClassName class]) {
NSAssert(nil, @"Subclassing MyFinalClassName not allowed.");
return nil;
}
return [super allocWithZone:zone];
}
This will prevent a subclass that is not a member of MyFinalClassName
from being alloc
'ed (and therefore init
'ed as well), since NSObject
's allocWithZone:
must be called eventually, and by refusing to call super
from your "final" class, you will prevent this.
There's a simpler way to prevent subclassing in Xcode 6 as a result of Swift interop. To prevent Swift classes from being subclassed in Objective-C the objc_subclassing_restricted
is added to all class definitions in the {ProjectName}-Swift.h
file.
You can use this in your projects:
#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
The compiler will halt on the definition of Bar
with Cannot subclass a class with objc_subclassing_restricted attribute
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