I've seen some sample code which has got me wondering about calling the designated initializer in the super classes. Say I have some code this:
@interface NewTableViewCell : UITableViewCell {
}
@end
@implementation NewTableViewCell
- (id) initWithFrame: (CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
// Do some stuff
}
return self;
}
@end
Note that initWithFrame
is the designated initializer for UIView
, not UITableView
. Should this code always be calling [UITableViewCell initWithStyle:reuseIdentifier:]
, or does it depend on the coder's intent?
This is called class inheritance or subclassing, the class you inherit from is called the “parent” or “super” class, and the new class is called the “child” class. For safety reasons, Swift always makes you call super. init() from child classes – just in case the parent class does some important work when it's created.
A convenience initializer is a secondary initializer that must call a designated initializer of the same class. It is useful when you want to provide default values or other custom setup. A class does not require convenience initializers.
The convenience initializer must call one of the two designated initializers, because it can only call another initializer from the same class. This satisfies rules 2 and 3 from above. Both designated initializers must call the single designated initializer from the superclass, to satisfy rule 1 from above.
Swift defines two kinds of initializers for class types to help ensure all stored properties receive an initial value. Designated initializers are the primary initializers for a class.
When a class calls the super method, it means it is a subclass of a superclass. You can also see this from the extends keyword after Car. Languages vary in how they handle inheritance so I won't go into that any further. From the example I provided above, the Car class is a subclass of the React.Component superclass.
If your superclass has no constructor, you don’t need to run the super () method in the constructor of your subclass. You can also use the super method to access other methods or information in the superclass. Using my initial React Car class, you can see from my IDE I have access to all the methods and properties of my Component superclass.
subclass (child) - the class that inherits from another class. superclass (parent) - the class being inherited from. To inherit from a class, use the extends keyword. In the example below, the Car class (subclass) inherits the attributes and methods from the Vehicle class (superclass):
In the example below, the Car class (subclass) inherits the attributes and methods from the Vehicle class (superclass): Did you notice the protected modifier in Vehicle? We set the brand attribute in Vehicle to a protected access modifier.
When subclassing, the guideline is that the designated initializer has to call its super class' designated initializer.
Another guideline is that the subclass needs to override the superclass' designated initializer to call the new designated initializer.
If UITableViewCell
follows this guideline (and it does; I tested with the help of a category), it overrides its superclass' designated initializer (UIView
's initWithFrame:
) to call the new designated initializer (initWithStyle:reuseIdentifier:
). Therefore, if you call initWithFrame:
on UITableViewCell
it will call initWithStyle:reuseIdentifier:
, which in turn will call initWithFrame:
on super
(UIView
).
Therefore, it will need an additional method call but it will eventually go through initWithStyle:reuseIdentifier:
.
Again, the best practice is that the designated initializer has to call the super class' designated initializer and any other initializer that isn't the designated initializer has to call the designated initializer. From "The Designated Initializer":
General principle: The designated initializer in a class must, through a message to super, invoke the designated initializer in a superclass.
Designated initializers are chained to each other through messages to super, while other initialization methods are chained to designated initializers through messages to self.
I agree it depends on the coders attempt but the coder should always try and use the designated initializer. Think about initializers you may have written, they probably do additional work for your object to be in a usable or desired state. If you are overriding an initializer like you are doing in your example you should call the overridden initializer as well. If that was a custom init method then you would want to call the designated initializer because for UITableViewCell
's that is the only way to set the reuseIdentifier publicly.
//Override initWithFrame
//Fine although it may not (should not) get called for a UITableViewCell
- (id) initWithFrame: (CGRect)frame {
self = [super initWithFrame:frame];
//Design a custom initializer to gather parameters for supers default initializer
-(id)initWithCustomObject:(id)object style:(UI..Style)style reuseIdentifier:(NSString*)rid {
//This should call initWithStyle:reuseIdentifier:
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