Lena Bru
Lena Bru

Reputation: 13947

Incorrect scope

I have two classes

A.h

@interface A : UIView

@end

A.m

@implementation A

-(id)initWithCoder:(NSCoder*)aDecoder{
  self = [super initWithCoder:aDecoder];
   if(self){ 
      [self initialize];
   }
return self;
}

-(void)initialize{
 [[NSNotificationCenter defaultCenter]addObserver:self name:keyboardnotificationwillshow];
}
@end

B.h

@interface B : A

@end

@implementation B

-(id)initWithCoder:(NSCoder*)aDecoder{
  self = [super initWithCoder:aDecoder];
   if(self){ 
      [self initialize];
   }
return self;
}

-(void)initialize{
 //do some stuff to prepare B
   [self setBackgroundColor:[UIColor redColor]];
}
@end

now i put B in the interface builder and wait for it to load via story board but!

now comes my question :

in all languages i've used to write code, the implementations i've written above would result in the following

  1. create B, call its initWithCoder method, see that it needs to go to super, goes to initWithCoder of A, see that it needs to call initialize in A (notice that initialize is an invented method, and its private, it is not declared in the h file of neither class), executes initialize that is written in A
  2. returns self, back to initWithCoder of B sees that it needs to execute initialize of B, executes initialize of B, returns B back to whomever wanted to create it with the coder

now i've run this through debug and this is the actual result: create B, initWithCoderB -> initWithCoderA ->initializeB ->return B

my actual question is :WHY did it skip initializeA ?

Log output

2014-05-19 14:45:23.270 MyApp[17780:60b] B initWithCoder
2014-05-19 14:45:23.270 MyApp[17780:60b] A initWithCoder
2014-05-19 14:45:23.272 MyApp[17780:60b] B initialize
2014-05-19 14:45:23.278 MyApp[17780:60b] B initialize

If i rename initializeA to initStuffA this is the log output

2014-05-19 14:48:41.700 MyApp[17795:60b] B initWithCoder
2014-05-19 14:48:41.701 MyApp[17795:60b] A initWithCoder
2014-05-19 14:48:41.701 MyApp[17795:60b] A initialize
2014-05-19 14:48:41.702 MyApp[17795:60b] B initialize

so why can't i have 2 methods with the same name as private, without them overriding eachother? because they are private, i cannot call super on them

Upvotes: 2

Views: 192

Answers (2)

Matthew Hallatt
Matthew Hallatt

Reputation: 1380

What exactly do you want to achieve here?

If you want an instance of interface B to go through the initWithCoder of interface A, then you have no need to overwrite it in interface B. Simply make initialize a public method and call:

- (void)initialize { [super initialize]; //Any further initialization here }

Currently, interface B has no idea that it's super class also implements a method called initialize as it is a private method.

If your initWithCoder: method in interface A calls your initialize method and it is a public method, then when you create an instance of interface B, it will go through the initWithCoder: of interface A, then through to the initialize of interface B which should then have a call to [super initialize]; to ensure any code in interface A's initialize method is executed.

EDIT 1:

Ok, so interface B inherits from interface A.

By default (ie, with a blank implementation), an instance of interface B will act exactly the same as interface A as all methods will default through to their implementation in interface A.

Interface B, being a child of interface A, has the opportunity to override any methods or properties made publicly available by interface A.

To make them publicly available, declare them in the .h file.

If you had a method, eg updateView in interface A's .h file, interface B's implementation then has the opportunity to override it. If you wanted interface B to perform the actions in both itself and interface A, you would need to call up the inheritance tree using the super keyword. For example, having something like the following in the implementation of interface B (the child):

- (void)updateView { [super updateView]; //This calls any code written in interface A's updateView method //Add your own code here }

This shows your subclass performing inheritance as it gains access to the updateView method created by interface A.

Interface B, as it is a child of interface A, will fill in any empty methods with the implementation from its parent class. In your example, you implemented initWithCoder: in both interfaces. This is unnecessary, and causes overwriting complications. By leaving out the declaration of initWithCoder: in interface B, it will use the implementation of it from interface A, its parent class, which calls to initialize. You simply have to remember to call to super every time you override a method implementation and wish to perform both your own code and that of the parent class.

Hopefully this clears up some of your confusions about inheritance within Objective-C.

Upvotes: 2

giorashc
giorashc

Reputation: 13713

Since you override the initialize method in class B and you are creating an instance of class B when the initialize method is called it will point to the deepest implementation in the inheritance hierarchy (which in your case is the initialize method of class B)

Upvotes: 3

Related Questions