2

人々がコメントの文脈を理解できるように、オリジナルを残しました。願わくば、この例が私が求めているものをよりよく説明するのに役立つことを願っています.

ファイル スコープの可視性を持つクラスを Obj-C で作成できますか?

たとえば、私は NSNotificationCenter にメソッド スクイズリング カテゴリを作成しました。このカテゴリは、オブザーバーが解放されると自動的に削除されます。

実装にはヘルパー クラスを使用し、名前の競合を防ぐために命名スキームを考案しました。カテゴリは NSNotificationCenter (WJHAutoRemoval) であるため、このコードで使用されるプライベート ヘルパー クラスの名前は...

WJH_NSNotification_WJHAutoRemoval__Private__BlockObserver

それは一口です、そして現在私はこれをやっています...

#define BlockObserver WJH_NSNotification_WJHAutoRemoval__Private__BlockObserver

コードで BlockObserver を使用するだけです。

しかし、私はその解決策が好きではありません。

コンパイラに、「ねえ、このクラスの名前は Bar です。私のコードは Bar としてアクセスしますが、実際に知る必要があるのは私だけです。自分でファンキーな名前を生成するか、できればそうしないでください」と伝えたいのです。気にする必要があるのは私だけなので、シンボルをエクスポートすることさえできます。」

普通の C の場合は「静的」で、C++ の場合は「名前空間 { }」です。

Obj-Cでこれを行うための推奨/最良/唯一の方法は何ですか?

元の質問

別の実装内でヘルパー クラスを使用したい。ただし、外部連携はしたくありません。現在、ヘルパー クラス名を非常にユニークなものにして、リンカー シンボルが重複しないようにしています。

静的 C 関数を使用できますが、コンパイル ユニット内でのみリンカーが表示されるヘルパー クラスを記述したいと考えています。

たとえば、次のようなものを複数の .m ファイルに入れたいと思います。各「ヘルパー」はそのファイルに固有であり、リンカー アクセスを持つ他のコンパイル ユニットはありません。これを 10 個の異なるファイルに入れると、10 個の個別のクラスになります。

@interface Helper : NSObject
...
@end

@implementation Helper : NSObject
...
@end

私はどこにもこれのヒントさえ見つけることができず、インターフェース/実装に「静的」を追加しようとする私の弱い試みはエラーで行われました.

ありがとう!

4

2 に答える 2

3

Objective-C ランタイムのおかげで、やりたいことができるとは思えません。すべてのクラスがランタイムにロードされ、同じ名前の複数のクラスが互いに競合します。

Objective-C は動的言語です。コンパイル時にメソッド呼び出しをバインドする他の言語とは異なり、Objective-C は呼び出し時に (すべての呼び出しで) メソッド解決を行います。ランタイムは、ランタイムでクラスを見つけてから、クラスでメソッドを見つけます。ランタイムは同じ名前の個別のクラスをサポートできず、Objective-C はクラスを分離するための名前空間をサポートしていません。

Helperそれぞれのケースでクラスが異なる場合は、個別のクラス名が必要になります (同じ名前の複数のクラスは、どの言語でも、私には悪い考えのように思えます) 。それらが同じである場合、なぜそれらを別々に宣言したいのですか。

あなたがしようとしていることは、Objective-C や Cocoa とは思えないので、戦略を再考する必要があると思います。

于 2012-05-14T15:07:44.230 に答える
0

クラスを「非表示」にする方法はありません。mttrb が指摘しているように、クラスはランタイムを通じて名前でアクセスできます。これは、クラスがリンカーによってアドレスに解決される単なるシンボルである C や C++ とは異なります。すべてのクラスがクラス階層に注入されます。

しかし、とにかくこれが必要な理由がわかりません。プライベート クラスなどがある場合WJHAutoRemovalHelper、プライベート Apple クラスやプライベート サードパーティ フレームワーク クラスが衝突する以上に、他の誰かと衝突する可能性は非常に低いようです。それをあいまいにするために英雄的な長さまで行く理由はありません。プレフィックスを付けるだけでWJHAutoRemoval、一意にすることができます。あなたが解決しようとしているより深い問題はありますか?

余談ですが、残りの部分はどのように実装していますか? オブザーバーを ISA-swizzling して、dealloc をオーバーライドしていますか? これは、非常に小さなことを少し便利にするための非常にトリッキーなコードのようです。


「プライベート」クラスの問題に関しては、あなたが提案していることは、手作業で行うことで可能ですが、実際には理由はありません。ランダムで一意のクラス名を生成し、それに対して and を呼び出しobjc_allocateClassPair()て、実行時にそれを変数にobjc_registerClassPair割り当てることができます。Class(そして、 と を呼び出しclass_addMethodclass_addIvar構築します。その後、必要なときにいつでもその変数で参照できます。もちろん、実行時に を呼び出すことでアクセスできますがobjc_getClassList、システムにはクラス名のシンボルはありません。

しかし、これは多くの作業と複雑さであり、何のメリットもありません。ObjC は、C++ のようにプログラム自体を保護することに多くの時間を費やしません。命名規則とコンパイラの警告を使用して、間違ったことをしているときに通知し、優れたプログラマーとして間違ったことを避けることを期待しています。

于 2012-05-14T20:47:00.770 に答える