Let's say I create my class and its init
method. Why should I call and return value of superclass init
assigned to self? Which cases it covers?
I would appreciate examples why would I need it for Cocoa superclass and non-Cocoa.
Answers
Calling the superclass's init
method and assigning its return value to self
is a standard practice in object-oriented programming, particularly in languages like Objective-C and Swift. This practice ensures that the object is properly initialized and inherits any setup or initialization logic defined in its superclass. Here's why you should do it:
1. Ensures Proper Initialization:
When you create a subclass, it inherits properties and behaviors from its superclass. By calling the superclass's init
method, you ensure that the superclass's initialization logic is executed, setting up any inherited properties and ensuring that the object is in a valid state. This is essential for the correct functioning of the subclass.
2. Allows Customization and Initialization:
By calling the superclass's init
method, you have the opportunity to customize the initialization process for your subclass. You can perform additional setup specific to your subclass before or after calling the superclass's init
method. This allows you to tailor the initialization process to the needs of your subclass.
3. Handles Inherited Initializers:
In Cocoa and Cocoa Touch frameworks, many classes provide designated initializers that must be called to properly initialize an object. By calling the superclass's designated initializer (typically init
or initWithFrame:
for views), you ensure that any required setup is performed. Failure to call the superclass's initializer may lead to undefined behavior or runtime errors.
Examples:
Cocoa Superclass (Objective-C):
@interface MyCustomView : UIView
@property (nonatomic, strong) UILabel *titleLabel;
@end
@implementation MyCustomView
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame]; // Call superclass's designated initializer
if (self) {
// Perform additional setup for MyCustomView
self.titleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
[self addSubview:self.titleLabel];
}
return self;
}
@end
In this example, MyCustomView
is a subclass of UIView
. By calling [super initWithFrame:frame]
, we ensure that the superclass's initialization logic for UIView
is executed, setting up the basic view properties. Then, we perform additional setup specific to MyCustomView
, such as creating a titleLabel
and adding it as a subview.
Non-Cocoa Superclass (Non-Objective-C):
class Vehicle {
var numberOfWheels: Int
init(numberOfWheels: Int) {
self.numberOfWheels = numberOfWheels
}
}
class Car: Vehicle {
var color: String
init(numberOfWheels: Int, color: String) {
self.color = color
super.init(numberOfWheels: numberOfWheels) // Call superclass's init
}
}
In this example (written in Swift), Vehicle
is a superclass with a designated initializer init(numberOfWheels:)
. Car
is a subclass of Vehicle
with an additional property color
. By calling super.init(numberOfWheels: numberOfWheels)
, we ensure that the superclass's initialization logic for Vehicle
is executed before performing additional setup specific to Car
.
Summary:
In both Cocoa and non-Cocoa scenarios, calling the superclass's init
method and assigning its return value to self
is crucial for proper object initialization and customization. It ensures that the superclass's initialization logic is executed and allows for subclass-specific setup. Failure to call the superclass's initializer may lead to undefined behavior or runtime errors.