プロトコルとカテゴリ
通信の契約を定義するプロトコルと、サブクラス化せずに既存クラスへメソッドを追加するカテゴリについて学びます。
「プロトコルとカテゴリ」はCoddyKit上の無料Objective-C iOS Development for Legacy & Enterprise Appsレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはObjective-C iOS Development for Legacy & Enterprise Apps学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Objective-C iOS Development for Legacy & Enterprise Appsコースには全4レッスンが含まれています。
このレッスンの一部はまだ翻訳されておらず、英語で表示されています。
Extending Behavior: Intro
Welcome to this lesson on Objective-C Protocols and Categories! These are powerful features that allow you to extend the functionality of your classes in flexible ways.
We'll explore how protocols define contracts for communication between objects and how categories let you add methods to existing classes without needing to subclass them.
Protocols: The Communication Contract
Think of an Objective-C protocol as a blueprint or a contract. It declares a list of methods that other classes can choose to implement.
- A class that 'adopts' a protocol promises to implement its required methods.
- This is crucial for establishing communication patterns, like the popular delegate pattern.
- Protocols are similar to interfaces in languages like Java or C#.
Defining a Protocol
To define a protocol, you use the @protocol directive. You can specify methods as @required (must be implemented) or @optional (can be implemented).
Protocols often conform to <NSObject>, meaning any class adopting it must be an Objective-C object.
@protocol MyServiceDelegate <NSObject>
@required
- (void)serviceDidFinishLoadingData:(NSArray *)data;
@optional
- (void)serviceDidStartRequest;
@endAdopting & Implementing a Protocol
A class adopts a protocol by listing it in angle brackets after its superclass. Then, it must implement all @required methods.
Let's see an example where a DataLoader class needs a delegate to tell it when data is ready.
#import <Foundation/Foundation.h>
// 1. Define the delegate protocol
@protocol DataLoaderDelegate <NSObject>
- (void)dataLoader:(id)loader didFinishLoadingData:(NSString *)data;
- (void)dataLoaderDidFail:(id)loader withError:(NSError *)error;
@end
// 2. Class that uses the delegate
@interface MyDataLoader : NSObject
@property (nonatomic, weak) id<DataLoaderDelegate> delegate; // The delegate property
- (void)loadData;
@end
@implementation MyDataLoader
- (void)loadData {
NSLog(@"DataLoader: Starting data load...");
// Simulate network request
NSString *result = @"Sample Data Loaded!";
// Notify the delegate
if ([self.delegate respondsToSelector:@selector(dataLoader:didFinishLoadingData:)]) {
[self.delegate dataLoader:self didFinishLoadingData:result];
}
}
@end
// 3. Class that conforms to the protocol (the delegate)
@interface MyDataConsumer : NSObject <DataLoaderDelegate> // Adopting the protocol
- (void)startConsumption;
@end
@implementation MyDataConsumer
- (void)startConsumption {
MyDataLoader *loader = [[MyDataLoader alloc] init];
loader.delegate = self; // Set self as the delegate
[loader loadData];
}
#pragma mark - DataLoaderDelegate Methods
- (void)dataLoader:(id)loader didFinishLoadingData:(NSString *)data {
NSLog(@"DataConsumer: Received data: %@", data);
}
- (void)dataLoaderDidFail:(id)loader withError:(NSError *)error {
NSLog(@"DataConsumer: Failed with error: %@", error.localizedDescription);
}
@end
// 4. Main execution
int main(int argc, const char * argv[]) {
@autoreleasepool {
MyDataConsumer *consumer = [[MyDataConsumer alloc] init];
[consumer startConsumption];
}
return 0;
}Categories: Extending Classes
Categories provide a way to add new methods to an existing class, even one you don't own (like NSString or NSObject), without modifying its original source code or creating a subclass.
- They are great for organizing code into logical groups.
- You cannot add new instance variables to a class using a category.
- If a category method has the same name as an existing method, the category's implementation will be used (this can lead to unexpected behavior!).
Defining a Category
To define a category, you create an interface file (.h) and an implementation file (.m). The syntax looks like this:
@interface ClassName (CategoryName)Let's create a category on NSString to add some utility methods.
// NSString+MyStringAdditions.h
#import <Foundation/Foundation.h>
@interface NSString (MyStringAdditions)
- (BOOL)isEmailValid;
- (NSString *)stringByCapitalizingFirstLetter;
@endImplementing Category Methods
Now let's implement the methods we declared in our NSString+MyStringAdditions category. Once implemented, these methods become available on any NSString instance!
Try running this example to see how it works:
#import <Foundation/Foundation.h>
// 1. Define the Category Interface
@interface NSString (MyStringAdditions)
- (NSString *)stringWithPrependedHello;
- (NSString *)stringWithAppendedExclamation;
@end
// 2. Implement the Category Methods
@implementation NSString (MyStringAdditions)
- (NSString *)stringWithPrependedHello {
return [NSString stringWithFormat:@"Hello, %@", self];
}
- (NSString *)stringWithAppendedExclamation {
return [NSString stringWithFormat:@"%@!", self];
}
@end
// 3. Main execution
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSString *name = @"CoddyKit";
// Use category methods
NSString *greeting = [name stringWithPrependedHello];
NSString *excitedGreeting = [greeting stringWithAppendedExclamation];
NSLog(@"Original: %@", name);
NSLog(@"Greeting: %@", greeting);
NSLog(@"Excited: %@", excitedGreeting);
}
return 0;
}When to Use Protocols vs. Categories
It's important to know when to choose between protocols and categories:
- Protocols: Use when you need to define a common interface or contract that multiple unrelated classes might conform to (e.g., delegate pattern, data sources). They define what an object can do.
- Categories: Use when you want to add utility methods to an existing class, group related methods, or extend a class without subclassing (e.g., adding a custom parsing method to
NSString). They extend how an object can behave.
Protocols & Inheritance
A protocol can also adopt other protocols, creating a hierarchy of requirements. For example, @protocol ChildProtocol <ParentProtocol> means ChildProtocol includes all methods from ParentProtocol.
This allows you to build more complex contracts by combining simpler ones.
Quick Check: Protocols
Consider the following Objective-C code snippet:
@protocol DataProcessor
@required
- (void)processData:(NSArray *)data;
@optional
- (void)didStartProcessing;
@end What is the primary purpose of this protocol?
Recap: Protocols & Categories
Great job! In this lesson, you learned about two powerful Objective-C features:
- Protocols: Define a contract of methods that classes can adopt to enable communication and establish common interfaces.
- Categories: Extend existing classes by adding new methods without inheritance, useful for utility functions and code organization.
Mastering these will help you build more flexible and modular Objective-C applications!
よくある質問
「プロトコルとカテゴリ」レッスンは無料ですか?
はい。「プロトコルとカテゴリ」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Objective-C iOS Development for Legacy & Enterprise Appsコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Objective-C iOS Development for Legacy & Enterprise Appsコースには全4レッスンが含まれています。
「プロトコルとカテゴリ」で何を学びますか?
通信の契約を定義するプロトコルと、サブクラス化せずに既存クラスへメソッドを追加するカテゴリについて学びます。 ブラウザで直接実行するハンズオンコードでObjective-C iOS Development for Legacy & Enterprise Appsを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Objective-C iOS Development for Legacy & Enterprise Appsを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのObjective-C iOS Development for Legacy & Enterprise Appsは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。
「プロトコルとカテゴリ」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このObjective-C iOS Development for Legacy & Enterprise Appsレッスンでコードを書いて実行できますか?
はい。すべてのObjective-C iOS Development for Legacy & Enterprise Appsレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。