gesnazo
gesnazo

Reputation: 19

Dynamic link / Dynamic typing in objective-c

I have seen in the BNR 3rd edition an example to do a static singleton class. To do that, they explain how to avoid a creation cycle calling the superclass alloc:

static MyClass *myclass = [[super alloc] init];

MyClass has its own init method.

NSObject -> MyClass

My doubt is: Which init class is sent? NSOject init, or MyClass init

Nested alloc init equals:

myclass = [super alloc] and then myclass = [myclass init] ???????????

OR

myclass = [super alloc] and then myclass = [super init]

Upvotes: 0

Views: 118

Answers (3)

gesnazo
gesnazo

Reputation: 19

Just for add some tests:

I have created 2 MyClass classes: NSObject -> Myclass -> My2ndClass

So:

@implementation Myclass
    +(id) sharedClass {
    static Myclass *miclase = nil;
    miclase = [[self alloc] init];    
    NSLog(@"%@", [super description]);
    return miclase;
}

-(id)init {    
    self = [super init];
    NSLog(@"init de Myclass");
    return self;
}
-(NSString *)description {
    return @"i am Myclass";
}
@end

AND:

@implementation My2ndClass
+(id) sharedClass {
    static My2ndClass *miclase = nil;
    miclase = [[super alloc] init];
    //miclase = [super init];  CRASH
    NSLog(@"%@", [super description]);
    return miclase;
}

-(id)init {    
    self = [super init];
    NSLog(@"init de My2ndClass");
    NSLog(@"%@", [super description]);
    return self;
}

-(NSString *)description {
    return @"i am My2ndClass";
}
@end

Then in AppDelegate:

Myclass *miclase = [Myclass sharedClass];
My2ndClass *mi2ndclase = [My2ndClass sharedClass];

This is the console output:

2012-09-03 17:18:55.742 Dynamic Typing[2891:207] init de Myclass
2012-09-03 17:18:55.744 Dynamic Typing[2891:207] Myclass
2012-09-03 17:18:55.746 Dynamic Typing[2891:207] init de Myclass
2012-09-03 17:18:55.747 Dynamic Typing[2891:207] init de My2ndClass
2012-09-03 17:18:55.748 Dynamic Typing[2891:207] i am Myclass
2012-09-03 17:18:55.751 Dynamic Typing[2891:207] My2ndClass

Like xlc0212 told, the correct messages when they are nested are:

miclase = [super alloc];
miclase = [miclase init];

Besides, if i do

miclase = [super alloc]

and then

miclase = [super init]

it CRASHES.

When is sent a class method (+) [super description], it logs class name (Myclass and My2ndClass). They are de class itself and don't have super object, do they?

Upvotes: 0

Bryan Chen
Bryan Chen

Reputation: 46598

for you question, the selector is always called on the subclass's implementation, which is your first guess

the way described in the book is a valid way to implement singleton, but i do not suggest it though. Robert Vojta's solution is good.

i cannot see how necessary to override allocWithZone, then you also need to make sure init does nothing (at least not leak)

Upvotes: 0

zrzka
zrzka

Reputation: 21259

Do not use super, but do use self. Otherwise subclassing of your singleton will not work. The correct way is something like this:

+ (MyClass *)sharedInstance {
  static MyClass *instance = nil;
  static dispatch_once_t onceToken;
  dispatch_once(&onceToken, ^{
    instance = [[self alloc] init];
  });
  return instance;
}

dispatch_once guarantees that your code (block in this case) is called only once. And self guarantees that subclassing will work properly.

Upvotes: 2

Related Questions