Objective-Cでのアクセス制御

初めまして。Inagoraの平田です。

C言語や他の言語はたっぷり経験しているのですが、Objective-C歴は1週間です。
Objective-Cでのアクセス制御についてカルチャーショックを受けたので記事にしたいと思います。

大抵のオブジェクト指向言語メソッドインスタンス変数(≒プロパティ)に対して以下のアクセス制御を明示的に行うことができ、そのための宣言構文を持っています。

private インスタンス外からはアクセス不可。クラス内からのみアクセス可能
protected インスタンス外からはアクセス不可。クラス内、その子クラス内からのみアクセス可能
public インスタンス外からアクセス可能

しかし、Objective-Cではそのような明示的な宣言がありません。
その代わりにヘッダファイルに記述する、しないで外部に公開するかどうかを決めます。
ヘッダファイル(*.h)に記述するのはpublic,ソースファイル(*.m)にのみ記述するのはprivateという感じです。簡単ですね。

Example.h

@interface Example:NSObject
@property boolean_t public_variable; //publicなプロパティ
- (void)public_method;               //publicなメソッド
@end


Example.m

#import "Example.h"

@implement

- (void)public_method {
  self.public_variable = true;
}

- (void)private_method {
  // privateなメソッド
}

@end

 

メソッドについては以上を理解していれば良いのですが、プロパティについてはもう一工夫が必要です。
プロパティを宣言するための@propertyは@interfaceの中にのみ記述でき、ソースファイルに記述される@implementの中には記述できないためです。
privateなプロパティを定義するためにはクラス拡張という機能を使います。
クラス拡張とは通常の@interfaceで宣言を記述したあとで、更に宣言を付け足す機能です。記述方法は"@implement クラス名()"と書きます。
これを用いて以下のようにソースファイル内で宣言を付け足すことでprivateなプロパティとすることができます。

Example.m

#import "Example.h"
    
@interface Example()

@property boolean_t private_variable; //プライベートなプロパティ

@end
    
@implement

- (void)public_method {
  self.public_variable = true;
  self.private_variable = true; // ヘッダファイルに書かれていないためこのソース外からは見えない。
}

@end

 

実はメソッドも同じように記述できるのですが、宣言なくても警告さえ出ないので私はやってません。

またprotected用のヘッダファイルを一つ追加し、それを自クラス、子クラスのソースファイルからのみインクルードする規約とすればprotectedも実現可能です。