Say I have this Class
@interface CustomClass : NSObject
@property (nonatomic, strong) NSArray * nicestArrayEver;
@end
And I want to create a subClass of CustomClass, but here is the catch
@interface ASubClassCustomClass : CustomClass
@property (nonatomic, strong) NSMutableArray * nicestArrayEver;
@end
The issue as you can imagine is that when I initialize ASubClassCustomClass and call it's super initializer (since there is other properties required) the inmutable nicestArrayEver is created.. how can I avoid it's creation so I can set the mutable one?
Note: This is just an example, the real implementation calls a heavy to create and really customized subclass (is not an NSArray).
A subclass can be further subclassed. Normally, subclassing specializes or refines a class by adding variables and methods (you cannot remove or hide variables or methods by subclassing).
A Java class can have only one direct superclass. Java does not support multiple inheritance. Creating a subclass can be as simple as including the extends clause in your class declaration (such as in the declaration in ImaginaryNumber above).
Can an object be a subclass of another object? A. Yes—as long as single inheritance is followed.
Subclass can not access parent private properties (fields) and methods. It can access public , protected and default properties and methods only.
You can make it work, by using different backing variables, when synthesizing it looks like this: @synthesize nicestArrayEver = nicestArrayEverSubClass_;
#import <Foundation/Foundation.h>
@interface CustomClass : NSObject
@property (nonatomic, strong) NSArray * nicestArrayEver;
@end
@implementation CustomClass
@synthesize nicestArrayEver ;
-(id)init
{
if (self = [super init]) {
nicestArrayEver = [[NSArray alloc] init];
}
return self;
}
@end
@interface ASubClassCustomClass : CustomClass
@property (nonatomic, strong) NSMutableArray * nicestArrayEver;
@end
@implementation ASubClassCustomClass
@synthesize nicestArrayEver = nicestArrayEverSubClass_;
-(id)init{
if (self = [super init]) {
nicestArrayEverSubClass_ = [[NSMutableArray alloc] init];
}
return self;
}
@end
int main(int argc, const char * argv[])
{
@autoreleasepool {
CustomClass *c1 = [[[CustomClass alloc] init] autorelease];
ASubClassCustomClass *c2 = [[[ASubClassCustomClass alloc] init] autorelease];
NSLog(@"%@", NSStringFromClass([[c1 nicestArrayEver] class]));
NSLog(@"%@", NSStringFromClass([[c2 nicestArrayEver] class]));
}
return 0;
}
output
2012-05-27 01:59:16.221 NicestArray[2312:403] __NSArrayI
2012-05-27 01:59:16.225 NicestArray[2312:403] __NSArrayM
Another approach could be to have 2 init methods in the base class, one, that will instantiate the property and one, that won't, but leaves that task for the child class — this will prevent you from creating expensive objects just to throw them away.
Now the base class could get instantiated directly with the second init and go to a false state. You can avoid this by checking the self class type with isMemberOfClass:
, and throw an error, if the class type is the base class.
@interface CustomClass : NSObject
@property (nonatomic, strong) NSArray * nicestArrayEver;
-(id)initWithoutArray;
@end
@implementation CustomClass
@synthesize nicestArrayEver ;
-(id) initWithoutArray
{
if (self = [super init]) {
if ([self isMemberOfClass:[CustomClass class]]) {
[NSException raise:@"AbstractMethodCall" format:@"%@ should be called only from Subclasses of %@", NSStringFromSelector(_cmd), NSStringFromClass([self class])];
}
}
return self;
}
-(id)init
{
if (self = [super init]) {
nicestArrayEver = [[NSArray alloc] init];
}
return self;
}
@end
@interface ASubClassCustomClass : CustomClass
@property (nonatomic, strong) NSMutableArray * nicestArrayEver;
@end
@implementation ASubClassCustomClass
@synthesize nicestArrayEver = nicestArrayEverSubClass_;
-(id)init{
if (self = [super initWithoutArray]) {
nicestArrayEverSubClass_ = [[NSMutableArray alloc] init];
}
return self;
}
@end
int main(int argc, const char * argv[])
{
@autoreleasepool {
CustomClass *c1 = [[[CustomClass alloc] init] autorelease];
ASubClassCustomClass *c2 = [[[ASubClassCustomClass alloc] init] autorelease];
NSLog(@"%@", NSStringFromClass([[c1 nicestArrayEver] class]));
NSLog(@"%@", NSStringFromClass([[c2 nicestArrayEver] class]));
//this works, as it is the subclass
ASubClassCustomClass *shouldWork = [[[ASubClassCustomClass alloc] init] autorelease];
// ouch!
CustomClass *shouldCrash = [[[CustomClass alloc] initWithoutArray] autorelease];
}
return 0;
}
I don't see the reason why you would want to do that, but I would advise you to do as follows: in your subclass declare a separate NSMutableArray property (let's call it nicestMutableArrayEver) and override the getter for your superclass NSArray property to return the mutableArray instance:
- (NSArray *)nicestArrayEver {
return [self nicestMutableArrayEver];
}
This way, you could get back your mutableArray whenever you reference the superclass property.
Best,
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