私の調査によると、 @privateディレクティブには実際の使用法がないことが示されています。そのため、何かが欠けている必要があり、専門家に協力してもらう必要があります:-)
CarクラスとSportsCarクラスの 2 つのクラスがあるとします。 SportsCarはCarのサブクラスです。
Carクラスは次のとおりです。
@interface Car : NSObject {
NSString *make;
NSString *model;
@private
int numberOfBackSeatPassengers; // I'm making this a private iVar cause I'm just gonna
// say that all Sportscars will be 2-seaters and therefore shouldn't
// be able to set/get the number of back-seat passengers
}
@property (nonatomic, strong) NSString *make, *model;
// Now here's my first issue: if I also make "numberOfBackSeatPassengers" an @property
// then it seems like all subclasses of this Car class *WILL* be able to access it as
// well - even though I declared it as @private - but I'll do this anyway to make my point:
@property int numberOfBackSeatPassengers;
@end
実装は次のようになります。
@implementation Car
@synthesize make, model, numberOfBackSeatPassengers;
@end
これがスポーツカークラスです。
#import "Car.h"
@interface Sportscar : Car
@property int turboEngineSize;
@end
そしてその実装:
#import "Sportscar.h"
@implementation Sportscar
@synthesize turboEngineSize;
@end
「メイン」にはこれがあります:
Car *car1 = [[Car alloc] init];
[car1 setMake:@"Chevy"];
[car1 setModel:@"Impala"];
[car1 setNumberOfBackSeatPassengers:3];
Sportscar *sports1 = [[Sportscar alloc] init];
[sports1 setMake:@"Audi"];
[sports1 setModel:@"tt"];
[sports1 setNumberOfBackSeatPassengers:3];
明らかに、iVar が@privateとして宣言されていても、スポーツカーにNumberOfBackSeatPassengerを設定できますが、それは「Car.h」で@propertyにしたためです。これは、合成されたゲッターとセッターがインスタンスであることを意味します。メソッド。これにより、 Carのすべてのサブクラスで使用できます。
もう 1 つのオプションは、「Car.h」で numberOfBackSeatPassengers を @property として宣言せず、単純な iVar として保持し、代わりに「Car.m」の @implementationで手動でセッターとゲッターを作成することでした。このような:
-(void) setNumberOfBackSeatPassengers:(int)numPassgeners {
numberOfBackSeatPassengers = numPassgeners;
}
-(int)numberOfBackSeatPassengers {
return numberOfBackSeatPassengers;
}
これにより、numberOfBackSeatPassengers のゲッターとセッターが" Car.m " 内でのみ使用可能になります (これにより、"プライベート" になると思います)。 「Car.m」 さらに、これが本当のポイントです。このようにすることは、「Car.h」の @private ディレクティブが実際にはまったく機能しないことを意味します。つまり、「Car.h」に戻って、そこにある「 @private」ディレクティブを取り出すことができます。また、numberOfBackSeatPassengersの手動セッターとゲッターは、現在とまったく同じように機能し、おそらくプライベートです。 「@private」で得られる ? それは実際にどのように機能しますか?
誰かがこれに本当の光を当てることができますか?
(そして、はい、 「Car.m」ファイルの @interface セクションで Car クラスを拡張できることを知っています-カテゴリを介して、または最初にnumberOfBackSeatPassengersを読み取り専用プロパティにしてから、それを readwrite に変更するなど-しかし、これらすべて「@private」を機能させるための回避策または「ハック」のように思えます.@privateが実際に単独でどのように機能するのかわかりません。)
================================================== ===
編集 - 以下のアロスのコメントに応えて:
1) を使用して、サブクラスがその親クラスのヘッダーで宣言されていないメソッドを理論的に呼び出すことができるという aroth の発言は絶対に正しいperformSelector
です。私は「理論的に」と言いますが、私の場合は正しく機能していないためです: if - 「メイン」で - 私は呼び出します
[sportscar1 performSelector:@selector(setNumberOfBackSeatPassengers:)];
numberOfBackSeatPassengers
次に、この方法でメソッドを呼び出すときに、数値を引数として明示的に渡すことができないため、ジャンク番号が挿入されます。
(質問: これを回避する方法はありますか?)
2) arothは、クラスの setter と getter をSportscar
単にオーバーライドして、これらのオーバーライド メソッドで 0 にリセットしたり、エラーを発生させたりすることもできます。しかし、これは非常に実用的な解決策であり、この特定の問題は、実際にはすべきことをしていないように見えるというより大きな問題に対処していないように感じます.Car
numberOfBackSeatPassengers
@private
3) ロジックを再設計して、クラスFourDoorCar
と別 のクラスを持ちTwoDoorCar
、それから構築を続けることは興味深いオプションですが、Objective-C の構文が自分のプログラミング ロジックと自分のやり方に「強制」されているように感じます。私のまさにプロジェクトを構築すること - そしてこれはかなりの負担のように感じます. 多分私は間違っていて、これを使いすぎているのかもしれませんが、どちらにしても@private
、約束されているように見えないという理由だけで、これはすべて起こりました...? 気分が悪い。
結局のところ、私は同じ質問に何度も戻って@private
きます。それにはどのような利点がありますか、何を「購入」しますか? iVar を非公開にしたい場合は、「.m」ファイルで宣言するだけでよく、最初からヘッダー ファイルで宣言する必要はないようです。私はこれについて正しいですか?または、ヘッダーでiVarを として宣言したいが、ヘッダーでセッターとゲッターを宣言したくないインスタンスがまだあります@private
-したがって、それらはサブクラスで明示的に利用できません-そしてそれをすべて作ります検出?
これについて実際の例を考えることができますか? 何らかの形で私に利益をもたらす (「.m」ではなく)@private
ヘッダーのように宣言したいある種の Car プロパティはありますか? 良い例だと思いnumberOfBackSeatPassengers
ましたが、実際のコードで実際にどのように機能するかわかりません...
================================================== =======================
編集 #2 - @aroth との対話を続ける :-)
@aroth - すべての iVar をヘッダーで宣言し、一部をヘッダーに、一部を実装に分割しない方がはるかに優れている/より組織化されていることに絶対に同意します。それは混乱を引き起こし、私はそのアプローチが本当に嫌いです。(元の質問で、質問に対処するために実装やカテゴリのアプローチを使用したくないことに注意しました。) -また、プロパティは常に iVar によってバックアップされる必要はありません。
-クラスを適切に設計することに関しては、もちろんそれが優れたプログラミングの鍵であることに同意します。車/スポーツカーの例は、質問に文脈を与えるためにその場で作り上げたものであり、その設計のメリット/欠陥を考慮して時間をかけませんでした. しかし、私たちがあなたのアプローチを採用した場合(これは確かに非常に論理的だと思われます)、Carクラス、FourDoorCarサブクラス、TwoDoorCarサブクラスなどを使用すると、多くの問題を解決できると思いますが、それでも可能性は非常に高いです遅かれ早かれ、クラスの 1 つに @private iVar が必要で、それを処理する別のサブクラスを作成したくないという状況に遭遇するでしょう。つまり、この議論のために、これが起こると仮定しましょう。
したがって、可能であれば、 @privateとして持つことが理にかなっている Car クラスの特定の iVar を考えて、その使用方法をコードで示し、その範囲と制限について説明したいと思います。
私は、Car だけに持たせたい、そしてそのサブクラスのどれも継承すべきではない Car のいくつかのプロパティの実世界の例を常に考えようとしています。私は本当にうまくいくと思っnumBackSeatPassengers
ていました-そして、私たちの議論の目的のために、それはまだできますが、私は別のものを作ってそれを呼びますphantomIVar
:-)
など:
@interface Car : NSObject {
@private
//int numberOfBackSeatPassengers;
int phantomIVar;
}
@property (nonatomic, strong) NSString *make, *model;
@end
実装は次のようになります。
@implementation Car
@synthesize make, model;
-(void) setPhantomIVar:(int)i {
phantomIVar = i;
}
-(int)phantomIVar {
return phantomIVar;
}
@end
これは、私たちが始めたところに戻ってきました:-)
少なくとも私はそう感じています。
つまり、@private
宣言が私たちを買収しているように見える唯一のことは、読みやすさです。そのため、ヘッダーを見ている人は誰でもphantomIVar
、それが Car の iVar であることがわかり、それが非公開であることを理解できます。それでおしまい。
ただし、機能面では、あまり機能していないように見えました。@private
解放された前に配置するのphantomIVar
とは異なり、ヘッダーにセッター/ゲッターを記述し、それらを Car クラス オブジェクトにのみアクセス可能にし、Car のサブクラスにはアクセスできないようにします。いいえ、それはわかりません@private
。プライバシーを確保するには、実装ファイルに移動して、そこにセッターとゲッターを記述する必要があります。そして最終的に、Objective-C にはプライベート メソッドのようなものはありません。オブジェクトで。C. それらはすべて公開されています。
ああ、これが正しいかどうか教えてください。そうでない場合は、どこで間違ったのか教えてください。
どうもありがとう :-)