Objective-Cでprivateなメソッドの実装

できません。

いや、ほんとに(´・ω・`) でも工夫すれば似たようなことができるのでその手法をメモ。

まずprivateメソッドって何ですか?って言う人はObjective-Cじゃなくてオブジェクト指向を勉強すること。 一人で開発していると特にメリットはないんだけど、 例えばライブラリを公開しようと思うと、他人には使って欲しくないメソッドがあったりする。 意地悪とかじゃなくて、処理用に実装した内部メソッドとかで。

例えば・・・いい例が思いつかないからちょっと冗長なん書いてみる。 まず値をセットして、その値を出力するプログラムがあったとする。 こんなん。

// ユーザに提供したいかけ算メソッド
- (int) getMulValue: (int) foo Bar: (int)bar{
 [self setX: foo]; 
 [self setY: bar]; //*1
 return [self mul]; //*2
}

// 1つ目の値をセットする内部メソッド
- (void) setX: (int) foo{
 X = foo;
}

// 2つ目の値をセットする内部メソッド
- (void) setY: (int) bar{
 Y = bar;
}

// 実際にかけ算を行うメソッド
- (int) mul{
 return X * Y;
}

この場合、当然ユーザに提供したいのは

- (int) getMulValue: (int) foo Bar: (int)bar;

だけで、

- (void) setX: (int) foo;

は使って欲しくない。 1と2の間にsetXされちゃうと、本来の値とは違う物が出力されるからだ。 (int) mulにしても、XやYがnilの時に呼び出して欲しくはないから公開したくない。 こういうとき、JavaなんかだとgetMulValueはpublic, setXやmulはprivateとして宣言する。

んで、その機能がないんですな。Objective-Cには。 全てのメソッド/オブジェクトがpublicとして提供される。 じゃあどうするか。

「要は、そういうメソッドがあることをユーザに教えなければよい」 という発想になります。 えー(´Д`;)

こんなんでもやらんよりましだ。 というわけでそのやり方。 端的に言うと、@interfaceをヘッダファイルに書かずに、実装ファイルの方に書いちゃう。 このときに、無名カテゴリを利用する。 こんなかんじ。

ヘッダファイル(Kakezan.h)

@interface Kakezan : NSObject {
 int X, Y;
}

- (int) getMulValue: (int) foo Bar: (int)bar;

実装ファイル(Kakezan.m)

#import "Kakezan.h"

@interface Kakezan ()//これが無名カテゴリ
- (void) setX: (int) foo;
- (void) setY: (int) bar;
- (int) mul;
@end

@implementation Kakezan
// ユーザに提供したいかけ算メソッド
- (int) getMulValue: (int) foo Bar: (int)bar{
 [self setX: foo]; 
 [self setY: bar]; //*1
 return [self mul]; //*2
}

// 1つ目の値をセットする内部メソッド
- (void) setX: (int) foo{
 X = foo;
}

// 2つ目の値をセットする内部メソッド
- (void) setY: (int) bar{
 Y = bar;
}

// 実際にかけ算を行うメソッド
- (int) mul{
 return X * Y;
}
@end

単にヘッダファイルに書かなければコンパイル後のバイナリとしては同じ事になるけど、 めんどくさがって無名カテゴリ使わないなんてことはやめた方がいい。保守性下がるし。

これ、どこかで見たことあるなぁと思ったら、iPhoneアプリ作るときに呼んだりする非公開メソッドそのものだ。 あれも、あっぷるさんがいじわるして使わせてくれない、のではなく、 多分勝手に呼んだらどっかでエラーが発生するんだろうなぁ。 自分でやってみると、あれがリジェクトされる理由がよく分かる。 リジェクトするくらいなら呼べないようにしとけよ、って言われても、できないもんね。

Java以降「バグの温床になりかねないものは使えないようにしよう」って考え方が流行っていて、 ポインタを隠蔽したりしているけど、 Objective-Cって、なんか、「え?そんなんプログラマが注意すりゃいんじゃね?」 って言い切っちゃう感じの部分がちらほら見られる。 過保護に対応するのに時間取るくらいなら、その分新しい機能追加したいし、 言語仕様が混乱したりする位なら情弱お断りって言っちゃえばよくね?みたいな。

Cの拡張だからそもそも対応できない部分が多くて、色々考えた末に割り切っちゃったんだろうな。きっと。 そういう選択と集中は嫌いじゃない。


そんな感じの言語なので、他の言語よりもきっちり勉強しておかないと足下すくわれるかもしれない。 と思ってこれの改訂前の奴を読み直している。 autorelease周りの挙動とか割と詳しく書いてるから、 コーディングするまえにしっかり読んでおけば良かった・・・ ありがちな、この言語のfor文はこんな書き方ですよーって感じの構文集ではなくて、 それ以降の人が参照するように記載してある。 そんなんWebで調べたら出てくるし、そっちの方がコピペも利くので、 この本のような内容を記述してある本でないと売れなくなっていくんだろうなぁと思う。

追記
その後のバージョンアップにより、ARCの機能でコンパイルエラーがでるようにはなりました。
ARCを切った際の挙動はこの記事のまま。

Written on April 9, 2011