私はObjective-Cのプログラミングを始めたばかりで、Javaの経験があるので、Objective-Cプログラムを書いている人がプライベートメソッドをどのように扱うのか疑問に思います。
私はいくつかの慣習や習慣があるかもしれないと理解していて、人々がObjective-Cのプライベートメソッドを扱うのに使う最も良いテクニックのアグリゲータとしてこの質問について考えます。
それを投稿するときあなたのアプローチのための議論を含めてください。どうしていいの?どのような欠点があるのか(あなたが知っていること)、そしてどのようにそれらに対処しますか?
私の調査結果はこれまでのところ。
カテゴリ [を使用することは可能です。 MyClass.mファイルでプライベートメソッドをグループ化するために定義されたMyClass(Private)]。
このアプローチには2つの問題があります。
最初の問題は 空のカテゴリ [で回避することができます。私のクラス ()]。
2番目のものは私をとても悩ませます。ファイルの終わり近くでプライベートメソッドを実装(および定義)してもらいたいのですが。それが可能かどうかはわかりません。
他の人がすでに言ったように、Objective-Cのプライベートメソッドのようなものはありません。ただし、Objective-C 2.0(Mac OS X Leopard、iPhone OS 2.0以降を意味)以降では、Class Extensionという名前の空の名前(つまり@interface MyClass ()
)でカテゴリを作成できます。クラス拡張のユニークな点は、メソッドの実装はパブリックメソッドと同じ@implementation MyClass
で行わなければならないということです。だから私はこのように私のクラスを構成します。
.hファイルでは、
@interface MyClass {
// My Instance Variables
}
- (void)myPublicMethod;
@end
そして.mファイルで:
@interface MyClass()
- (void)myPrivateMethod;
@end
@implementation MyClass
- (void)myPublicMethod {
// Implementation goes here
}
- (void)myPrivateMethod {
// Implementation goes here
}
@end
このアプローチの最大の利点は、メソッド実装を機能ごとにグループ化できることです。パブリック/プライベートの区別ではない場合があります。
私はObjective-Cの専門家ではありませんが、自分のクラスの実装でメソッドを定義するだけです。確かに、それはそれを呼び出すメソッドの前に(上で)定義されていなければなりませんが、それは間違いなく行うべき仕事の最小量を取ります。
プライベートメソッドを@implementation
ブロックで定義することは、ほとんどの目的に理想的です。 Clangは宣言順に関係なく、これらを@implementation
内に表示します。それらをクラス継続(別名クラス拡張)または名前付きカテゴリで宣言する必要はありません。
場合によっては、クラス継続でメソッドを宣言する必要があります(たとえば、クラス継続と@implementation
の間のセレクタを使用する場合)。
static
関数は、特に機密性が高い、またはスピードが重要なプライベートメソッドに非常に適しています。
接頭辞の命名規則は、プライベートメソッドを誤ってオーバーライドしないようにするのに役立ちます(クラス名は接頭辞として安全です)。
名前付きカテゴリ(例:@interface MONObject (PrivateStuff)
)は、ロード時に名前が衝突する可能性があるため、特にお勧めできません。それらは、本当に友人や保護されたメソッドにしか役に立ちません(これはめったに良い選択ではありません)。カテゴリの実装が不完全であることを警告するために、実際に実装する必要があります。
@implementation MONObject (PrivateStuff)
...HERE...
@end
これはちょっと注釈付きのチートシートです:
MONObject.h
@interface MONObject : NSObject
// public declaration required for clients' visibility/use.
@property (nonatomic, assign, readwrite) bool publicBool;
// public declaration required for clients' visibility/use.
- (void)publicMethod;
@end
MONObject.m
@interface MONObject ()
@property (nonatomic, assign, readwrite) bool privateBool;
// you can use a convention where the class name prefix is reserved
// for private methods this can reduce accidental overriding:
- (void)MONObject_privateMethod;
@end
// The potentially good thing about functions is that they are truly
// inaccessible; They may not be overridden, accidentally used,
// looked up via the objc runtime, and will often be eliminated from
// backtraces. Unlike methods, they can also be inlined. If unused
// (e.g. diagnostic omitted in release) or every use is inlined,
// they may be removed from the binary:
static void PrivateMethod(MONObject * pObject) {
pObject.privateBool = true;
}
@implementation MONObject
{
bool anIvar;
}
static void AnotherPrivateMethod(MONObject * pObject) {
if (0 == pObject) {
assert(0 && "invalid parameter");
return;
}
// if declared in the @implementation scope, you *could* access the
// private ivars directly (although you should rarely do this):
pObject->anIvar = true;
}
- (void)publicMethod
{
// declared below -- but clang can see its declaration in this
// translation:
[self privateMethod];
}
// no declaration required.
- (void)privateMethod
{
}
- (void)MONObject_privateMethod
{
}
@end
明白ではないかもしれないもう一つのアプローチ:C++型は非常に高速であり、エクスポートされロードされたobjcメソッドの数を最小にしながらはるかに高度な制御を提供することができます。
あなたはあなたのインスタンスへのポインタを取るあなたの実装の上下に静的関数を定義することを試みることができます。インスタンス変数にアクセスできます。
//.h file
@interface MyClass : Object
{
int test;
}
- (void) someMethod: anArg;
@end
//.m file
@implementation MyClass
static void somePrivateMethod (MyClass *myClass, id anArg)
{
fprintf (stderr, "MyClass (%d) was passed %p", myClass->test, anArg);
}
- (void) someMethod: (id) anArg
{
somePrivateMethod (self, anArg);
}
@end
あなたはブロックを使うことができますか?
@implementation MyClass
id (^createTheObject)() = ^(){ return [[NSObject alloc] init];};
NSInteger (^addEm)(NSInteger, NSInteger) =
^(NSInteger a, NSInteger b)
{
return a + b;
};
//public methods, etc.
- (NSObject) thePublicOne
{
return createTheObject();
}
@end
これは古い質問ですが、この質問に対する答えを探していたときに最初に見つけた質問の1つです。私はこの解決策が他で議論されるのを見たことがないので、これをすることについて何かばかなことがあるかどうか私に知らせてください。
objective Cのすべてのオブジェクトは、performSelector:メソッドを保持するNSObjectプロトコルに準拠しています。私は以前、パブリックレベルで公開する必要のない「ヘルパーまたはプライベート」メソッドを作成する方法も探していました。あなたがオーバーヘッドなしであなたのヘッダファイルでそれを定義する必要がないプライベートメソッドを作成したいなら、これに打撃を与える...
下記のコードのようなシグネチャであなたのメソッドを定義してください...
-(void)myHelperMethod: (id) sender{
// code here...
}
その後、メソッドを参照する必要があるときは、単にセレクタとしてそれを呼び出すだけです。
[self performSelector:@selector(myHelperMethod:)];
このコード行は、作成したメソッドを呼び出しますが、ヘッダーファイルで定義されていないことについての煩わしい警告はありません。
先頭の@interface
ブロックを避けたい場合は、プライベート宣言を常に別のファイルに入れることができます。MyClassPrivate.h
は理想的ではありませんが、実装が散らかっていません。
MyClass.h
interface MyClass : NSObject {
@private
BOOL publicIvar_;
BOOL privateIvar_;
}
@property (nonatomic, assign) BOOL publicIvar;
//any other public methods. etc
@end
MyClassPrivate.h
@interface MyClass ()
@property (nonatomic, assign) BOOL privateIvar;
//any other private methods etc.
@end
MyClass.m
#import "MyClass.h"
#import "MyClassPrivate.h"
@implementation MyClass
@synthesize privateIvar = privateIvar_;
@synthesize publicIvar = publicIvar_;
@end
私がここで言及していないもう一つのこと - Xcodeは名前に "_private"を持つ.hファイルをサポートします。 MyClassというクラスがあるとしましょう - MyClass.mとMyClass.hがあり、そして今度はMyClass_private.hも持つことができます。 Xcodeはこれを認識し、アシスタントエディタの「カウンターパート」のリストに含めます。
//MyClass.m
#import "MyClass.h"
#import "MyClass_private.h"
問題#2を回避する方法はありません。それがまさにCコンパイラ(そしてそれゆえObjective-Cコンパイラ)が働く方法です。 XCodeエディタを使用する場合は、関数popupを使用すると、ファイル内の@interface
ブロックと@implementation
ブロックを簡単にナビゲートできるはずです。
プライベートメソッドがないことの利点があります。隠したいロジックを別のクラスに移動してデリゲートとして使用することができます。この場合、あなたはデリゲートオブジェクトをプライベートとしてマークすることができ、それは外部から見えなくなります。ロジックを別のクラス(おそらく複数)に移動すると、プロジェクトの設計が改善されます。クラスが単純になり、メソッドが適切な名前のクラスにまとめられるようにします。
他の人々が@implementation
ブロックでプライベートメソッドを定義することはほとんどの目的のためにOKであると言ったように。
code organization - の話題で、私はXcodeでのナビゲーションを容易にするためにそれらをpragma mark private
の下にまとめておくのが好きです
@implementation MyClass
// .. public methods
# pragma mark private
// ...
@end