100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Programming

Inheritance in Objective-C

How Objective-C's single-inheritance class hierarchy works, including method overriding, calling super, and designated initializers.

OOP in Objective-CIntermediate10 min readJul 10, 2026
Analogies

Inheritance in Objective-C

Objective-C supports single inheritance: a class declared as @interface Dog : Animal states that Dog inherits every property and method Animal defines, and adds or overrides behavior on top, but a class can only have exactly one direct superclass, unlike languages such as C++ that permit multiple inheritance. Every class ultimately traces a single unbroken chain of superclasses up to NSObject, and an object of a subclass can be used anywhere an instance of its superclass is expected, the core mechanic behind polymorphism.

🏏

Cricket analogy: Like a domestic player inheriting all the fundamentals from their state academy's coaching before adding their own signature shot at the international level, a subclass inherits its superclass's behavior before adding its own.

Overriding Methods and Calling super

A subclass overrides an inherited method by declaring a method with the exact same signature in its own @implementation; when that method is called on a subclass instance, the subclass version runs instead of the superclass version, which is polymorphism in action. Inside an override, calling [super methodName] explicitly invokes the superclass's version of that same method, letting the subclass extend rather than fully replace the inherited behavior, a pattern used constantly for initializers (self = [super init]) and lifecycle methods like viewDidLoad in UIKit.

🏏

Cricket analogy: Like a franchise's new head coach keeping the previous coach's core fielding drills (calling super) but adding an extra fitness session on top, an override that calls super extends the inherited behavior rather than discarding it.

Designated Initializers and the Initializer Chain

In a class hierarchy, the designated initializer is the one method fully responsible for calling up the chain via [super init...] and setting every one of a class's own instance variables; other initializers on the same class, called convenience initializers, should funnel through that same designated initializer rather than duplicating its setup logic, and a subclass must override its superclass's designated initializer (or provide its own that calls it) to guarantee the full chain of ancestor setup runs in order. Using instancetype instead of id as the return type for initializers lets the compiler correctly infer the concrete subclass type when a subclass calls an inherited initializer, avoiding an id downcast at the call site.

🏏

Cricket analogy: Like a fast bowler's run-up having one designated full approach that every delivery variation, yorker, bouncer, slower ball, must funnel through rather than skipping steps, a designated initializer is the one setup path every other initializer must funnel through.

objectivec
// Animal.h
@interface Animal : NSObject
@property (nonatomic, copy) NSString *name;
- (instancetype)initWithName:(NSString *)name; // designated initializer
- (void)makeSound;
@end

// Animal.m
@implementation Animal
- (instancetype)initWithName:(NSString *)name {
    self = [super init];
    if (self) {
        _name = [name copy];
    }
    return self;
}
- (void)makeSound {
    NSLog(@"%@ makes a generic sound.", self.name);
}
@end

// Dog.h
@interface Dog : Animal
@end

// Dog.m
@implementation Dog
- (void)makeSound {
    [super makeSound];           // extend, don't replace
    NSLog(@"%@ barks: Woof!", self.name);
}
@end

// usage: polymorphism in action
Animal *pet = [[Dog alloc] initWithName:@"Rex"];
[pet makeSound]; // prints the generic line, then "Rex barks: Woof!"

NSObject's class hierarchy is single-rooted and single-inheritance only, but Objective-C compensates for the lack of multiple inheritance through protocols, which let a class conform to multiple independent contracts (see the Protocols and Delegation topic) without the diamond-inheritance ambiguity multiple class inheritance would introduce.

Forgetting to call [super ...] inside an overridden method, especially inside init or a UIKit lifecycle method like viewDidLoad, is one of the most common Objective-C bugs: it silently skips whatever setup the superclass was responsible for, which can leave the object in a broken or partially initialized state without any compiler warning.

  • Objective-C supports single inheritance only: a class has exactly one direct superclass.
  • Every class traces an unbroken chain of superclasses up to the root class, NSObject.
  • Overriding a method means declaring a same-signature method in the subclass; the subclass version runs at call time.
  • Calling [super methodName] inside an override invokes the superclass's version, extending rather than replacing it.
  • The designated initializer is the one method responsible for calling super's initializer and setting all of a class's ivars.
  • Convenience initializers should funnel through the designated initializer instead of duplicating its setup.
  • instancetype as an initializer's return type lets the compiler infer the correct concrete subclass type.

Practice what you learned

Was this page helpful?

Topics covered

#Programming#ObjectiveCStudyNotes#InheritanceInObjectiveC#Inheritance#Objective#Overriding#Methods#OOP#StudyNotes#SkillVeris