👀

【Objective-C】面食らわないためのObjective-Cの読み方

2024/08/09に公開

この記事は

先日 React Native を書いていて Native Module を自作することになり、どうしてもObjective-Cを読むことが求められました。このような場面で参考にできるドキュメントのがあまりないと感じ、現代の平均的な言語と比較すると異色さが際立つ、 Class 周りについて重点的にまとめました。

ファイル構成・基本的なClassの宣言

Objective-Cでは、CとかC++に同じく、実装ファイル(.m)とヘッダーファイル(.h)の2種類のファイルにソースコードを記述していきます。言語思想として、ヘッダーファイルにはある Class のパブリックなメンバ・メソッドなど、そのClassが外部からどのように見えるのかを記述し、その Class の内部実装は実装ファイルにのみ記述することで、インターフェイスを独立して明文化でき、他の Class から実装の詳細を隠蔽することができる仕組みになっています(ヘッダーファイルと実装ファイルの切り分けが秀逸【Objective-Cの良い所 その4】) 。

これら2種類のファイルに具体的な記述として、実装ファイルに@implementationというコンパイラディレクティブとともに具体的な実装が記述されます。ヘッダーファイルには@interfaceでそのClassの外部から見た振る舞いが記述されます。コンパイラの事情で必要なヘッダーファイルが、OOPで言うところのインターフェース的な役割も兼ねていると言えるでしょう。

Class.h
@interface Person: NSObject
@property NSString: name
@end
Class.m
@implementation Person {
  NSString name;
  float height;
}
- (void) getHeight {
  return self.height
}

引数を取るメソッド

Class.h
@interface Person: NSObject
@property NSString: name
(float) calcHeight:(float)arg1  myArg2:(float)arg2
@end
Class.m
@implementation Person {
  NSString name;
  float height;
}
- (void) getHeight {
  return self.height
}

クラス変数・インスタンス変数・クラスメソッド・インスタンスメソッド

Class.m
@implementation Person
  { float height }
  NSString name
  - (int)instanceMethod { return ++local; }
  + (int)classMethod    { return ++global; }
@end

Class を使用する

メソッドを呼び出す

Class.m
# インスタンスを生成する(記法a)
Person* a = [[Person alloc] init];
# インスタンスを生成する(記法b)
Person* b = [Person new];
# 引数のないメソッドを呼び出す
[Person calcHeight]
# 引数のあるメソッドを呼び出す
[Person calcHeight:1 MyArg2:2]

よく分からない[]が登場します。これはメッセージ式という Smalltalk から受け継がれた概念で、Object 同士が会話をするようなイメージらしいです。

参考

Discussion