Objective-Cのクラスやプロパティ、特徴的なメソッドの使い方:iOS SDKで始めるObjective-C入門(7)(3/3 ページ)
開発ツールXcode/iOS SDKを使ってiPhone/iPadアプリを作る方法を、プログラミング言語「Objective-C」の書き方/文法を交えて解説。「Windowsを使っていたけど、iOSアプリを作るためにMacを使い始めた」という初心者を対象にしています。今回は、クラス、プロパティ、メソッドを中心にインポート、アクセサー(ゲッター、セッター)、引数とラベ、スコープ、selfとsuperなどについてもコードを交えて説明します。
メソッド
メソッドの話はこれまでもたびたび出てきましたが、詳しい書き方についてはまだ解説していませんでした。ここからは、メソッドの書き方について解説していきます。
他の言語を使っていた方にとっては、一番違和感を持たれるところかもしれません。ですが、基本的なことはほとんど同じです。なので、どんどん慣れていきましょう。
メソッドの定義の仕方
メソッドを定義するには、以下のように記述します。
- (戻り値の型)メソッド名 { // メソッドの実装 }
値を返す「return文」
例えば、「- (NSString *)name」メソッドは、「NSString型の値を返すnameという名前のメソッド」です。「返す」というのは、return文を使って値を返すことを指します。
「- (NSString *)name」メソッドでは、NSString型の値を返しているので、戻り値の型にはNSStringを指定しています。
// 名前を取得する - (NSString *)name { return _name; }
戻り値がない場合は「void」
ここで、「- (void)setName:」メソッドを見てみましょう。戻り値の型にvoidが指定されています。このように、戻り値がない場合は、voidを指定します。
// 名前を設定する - (void)setName:(NSString *)name { _name = name; }
メソッドの「引数」と「ラベル」
また、「- (void)setName:」メソッドでは、メソッド名の後に「コロン(:)」があります。これは、引数といって、メソッドに値を渡す必要がある場合に使用します。
引数は1つだけではなく、複数指定できます。その場合、以下のように記述します。
// 引数が3つの場合 - (戻り値の型)メソッド名:(引数の型)引数1 ラベル:(引数の型)引数2 ラベル:(引数の型)引数3
引数に「ラベル」を付けるのがObjective-Cの特徴の1つですが、他の言語を使っていた方から見ると少し冗長に思えるかもしれません。実はこのラベルは省略できます。一方で、この書き方こそがObjective-Cの魅力の一つといえます。
例えば、以下のメソッドを見てみましょう。
- (BOOL)writeToFile:(NSString *)path atomically:(BOOL)useAuxiliaryFile encoding:(NSStringEncoding)enc error:(NSError **)error;
このメソッドはNSStringクラスで定義される文字列をファイルに書き出すメソッドです。書き出す際に文字のエンコードや「アトミックにファイルに書き出すかどうか」などを指定できます。このメソッドを使用するには、以下のように記述します。
NSString *str = @"文字列"; NSError *error = nil; [str writeToFile:@"write/to/path" atomically:YES encoding:NSUTF8StringEncoding error:&error];
これを、ラベルが指定されていないと仮定して記述すると、以下のようになり、どういう順序でどういう引数が渡せるのか分かりにくくなってしまいます。
NSString *str = @"文字列"; NSError *error = nil; [str writeToFile:@"write/to/path" :YES :NSUTF8StringEncoding :&error];
このように、ラベルを指定することで利用使用としているメソッドにどんな引数が渡せるか一目で理解できます。Objective-Cにおいては、冗長的であってもなるべく省略した記述をせずに、パッと見ただけでどんな機能を持つか分かりやすく記述することが慣例となっています。
ですので、面倒であってもメソッドを定義する際はこのことを意識し、使う人にとってより分かりやすく名前を付けるよう心掛けましょう。
コラム「インスタンスメソッドとクラスメソッド」
戻り値の前に「マイナス(-)」があることにお気付きでしょうか。これは、このメソッドがインスタンスメソッドであることを示しています。インスタンスメソッドはクラスをインスタンス化して初めて実行できるメソッドです。マイナスがあればプラスもあります。
マイナスではなくて「プラス(+)」を指定すると、そのメソッドはクラスメソッドになります。クラスメソッドはインスタンス化しなくても使えるメソッドです。
プロパティとメソッドのスコープ
Objective-Cでは、他のクラスからプロパティへのアクセスやメソッドの呼び出しを行えるようにするために、それらの宣言をヘッダーファイルに記載します。
例えば、以下のように記述すると「name」「age」プロパティと「- displayProfile」メソッドに対して、他のクラスから参照できます。
#import <Foundation/Foundation.h> @interface Person : NSObject // 名前 @property (nonatomic) NSString *name; // 年齢 @property (nonatomic) NSInteger age; // 名前をログに出力する - (void)displayName; // 年齢をログに出力する - (void)displayAge; // 名前と年齢をログに出力する - (void)displayProfile; @end
ヘッダーファイルに宣言されたプロパティやメソッドは全て他のクラスから参照できる状態、すなわち公開(Public)されてしまいます。
しかも、Objective-Cにはプロパティやメソッド非公開にするための言語的機能がありません。
そのため、以下のように実装ファイルで宣言を行い、疑似的に非公開(Private)にすることが可能です。
#import <Foundation/Foundation.h> @interface Person : NSObject // 名前 @property (nonatomic) NSString *name; // 名前と年齢をログに出力する - (void)displayProfile; @end
#import <Foundation/Foundation.h> @interface Person () // 年齢 @property (nonatomic) NSInteger age; // 名前をログに出力する - (void)displayName; // 年齢をログに出力する - (void)displayAge; @end @implementation Person …… @end
こうすることで、「age」プロパティと「- displayName」メソッド、「- displayAge」メソッドは他のクラスから参照できなくなります。
実装ファイルに書かれている「@interface Person () …… @end」ですが、これは「クラスエクステンション」と呼ばれる機能で、文字通りクラスを拡張する機能です。この機能を利用して疑似的にプライベートにすることが可能です。
なお、「@implementation …… @end」で実装されているメソッドに関しては、クラスエクステンション部分に宣言しなくてもヘッダーに記述しなければ、プライベート扱いになります。
selfとsuper
メソッド内で、自分自身のインスタンス変数やメソッドにアクセスするには、selfを使用します。JavaやC#でいうところの「this」のようなものです。
- (void)displayProfile { NSLog(@"私の名前は%@です。年齢は%d歳です。", self.name, self.age); }
また、親クラスのインスンタンス変数やメソッドにアクセスするときは、superを使用します。これは、Javaでは同じく「super」、C#でいうところの「base」のようなものです。
プロトコル、カテゴリ、デリゲートについては、後の連載で
Objective-Cには、ここまで紹介した以外にもたくさんの機能が備わっています。また、ここでは紹介し切れなかった重要な機能として「プロトコル」「カテゴリ」「デリゲート」という機能がありますが、これらについては順次説明していこうと思います。
また、現段階で今回まで解説した内容をすべて理解しておく必要はありません。使い方を覚える一番の近道は「アプリを実際に作ること」に他なりません。
ということで、次回からはようやくiOSアプリの開発の話に入りたいと思います。お楽しみに!
Copyright © ITmedia, Inc. All Rights Reserved.