Objective-C - Categories Extend Existing Classes

«  Objective-C - An App Is Built from a Network of Objects
Objective-C - Protocols Define Messaging Contracts  »

Customizing Existing Classes

Objective-C allows you to add your own methods to existing classes through categories and class extensions.

Categories Add Methods to Existing Classes

If you need to add a method to an existing class, perhaps to add functionality to make it easier to do something in your own application, the easiest way is to use a category.

The syntax to declare a category uses the @interface keyword, just like a standard Objective-C class description, but does not indicate any inheritance from a subclass. Instead, it specifies the name of the category in parentheses

/* Category */
@interface ClassName (CategoryName)
 
@end

// ------ Sample ------
// interface
#import "XYZPerson.h"
 
@interface XYZPerson (XYZPersonNameDisplayAdditions)
- (NSString *)lastNameFirstNameString;
@end

// implementation
#import "XYZPerson+XYZPersonNameDisplayAdditions.h"
 
@implementation XYZPerson (XYZPersonNameDisplayAdditions)
- (NSString *)lastNameFirstNameString {
    return [NSString stringWithFormat:@"%@, %@", self.lastName, self.firstName];
}
@end

#import "XYZPerson+XYZPersonNameDisplayAdditions.h"
@implementation SomeObject
- (void)someMethod {
    XYZPerson *person = [[XYZPerson alloc] initWithFirstName:@"John"
                                                    lastName:@"Doe"];
    XYZShoutingPerson *shoutingPerson =
                        [[XYZShoutingPerson alloc] initWithFirstName:@"Monica"
                                                            lastName:@"Robinson"];
 
    NSLog(@"The two people are %@ and %@",
         [person lastNameFirstNameString], [shoutingPerson lastNameFirstNameString]);
}
@end

Class Extensions Extend the Internal Implementation

Because no name is given in the parentheses, class extensions are often referred to as anonymous categories.

Unlike regular categories, a class extension can add its own properties and instance variables to a class.

The compiler will automatically synthesize the relevant accessor methods, as well as an instance variable, inside the primary class implementation.

If you add any methods in a class extension, these must be implemented in the primary implementation for the class.

/* Declare class extension */
@interface ClassName ()
 
@end

// ------ Sample ------
@interface XYZPerson ()
@property NSObject *extraProperty;
@end

The primary interface for a class is used to define the way that other classes are expected to interact with it. In other words, it’s the public interface to the class.

Class extensions are often used to extend the public interface with additional private methods or properties for use within the implementation of the class itself.

@interface XYZPerson : NSObject
...
@property (readonly) NSString *uniqueIdentifier;
- (void)assignUniqueIdentifier;
@end

// In order for the XYZPerson class to be able to change the property internally, it makes sense to redeclare the property in a class extension that’s defined at the top of the implementation file for the class:
//
// This means that the compiler will now also synthesize a setter method, so any method inside the XYZPerson implementation will be able to set the property directly using either the setter or dot syntax.

@interface XYZPerson ()
@property (readwrite) NSString *uniqueIdentifier;
@end
 
@implementation XYZPerson
...
@end

Consider Other Alternatives for Class Customization

One of the primary goals of object-oriented programming is to write reusable code, which means that classes should be reusable in a variety of situations, wherever possible.

one alternative is to leverage inheritance and leave those decisions in methods specifically designed to be overridden by subclasses. Although this does make it relatively easy to reuse the class, you still need to create a new subclass every time you want to make use of that original class.

Another alternative is for a class to use a delegate object. Any decisions that might limit reusability can be delegated to another object, which is left to make those decisions at runtime.

Objective-C also offers dynamic behavior through runtime system, ex: use associated references to object.

Reference

Published on 13 Oct 2020 Find me on Facebook, Twitter!

«  Objective-C - An App Is Built from a Network of Objects
Objective-C - Protocols Define Messaging Contracts  »

Comments

    Join the discussion for this article at here . Our comments is using Github Issues. All of posted comments will display at this page instantly.