web-dev-qa-db-ja.com

Objective-Cで保護されたプロパティを達成するための回避策

私は、Objective-Cで@protectedプロパティを宣言して、階層内のサブクラスのみがそれらにアクセスできるようにする(読み取り専用、書き込みではない)回避策を見つけようとしました。これを行うための文書化された方法がないことを読んだので、この回避策を考え、それについてStackOverflowの意見を聞きたかった。

階層の最上位にあるすべてのカスタムクラスには、3つのクラス、1つの実装、2つのインターフェイスが含まれています。それらに名前を付けましょう:

ClassA.h
ClassA_protected.h
ClassA.m

次に、このClassAのサブクラスは通常どおりになります。

ClassB.h
ClassB.m

まず、インターフェイスClassA.hを作成しました。ここで、保護されたint変数を宣言して、ClassAのすべてのサブクラスがアクセスできるようにします。

@interface ClassA : NSObject{
    @protected
    int _myProtectedInt;
}
@end

次のステップは、私が話していた回避策です。しかし、それを読むと、それは非常に簡単であることがわかります。 ClassA_protected.hと呼ばれる2番目のインターフェイスを宣言しました。これは実際にはClassA.hのextensionとして機能し、タグを付けることができますreadonlyとしてのプロパティ:

#import "ClassA.h"
@interface ClassA ()
@property (nonatomic , readonly) int myProtectedInt;
@end

保護された階層を準備する最後のステップは、プロパティの合成のみを行うClassA.mでその実装を宣言することです。

#import "ClassA_protected.h"
@implementation ClassA
@synthesize myProtectedInt = _ myProtectedInt;
@end

このように、ClassA.hのサブクラスである必要があるすべてのクラスは、代わりにClassA_protected.hをインポートします。したがって、たとえばClassB.hのような子は次のようになります。

#import "ClassA_protected.h"
@interface ClassB : ClassA
@end

そして、このプロパティにClassB.mの実装からアクセスする例:

@implementation ClassB
-(void) method {
    //edit protected variable 
    _myProtectedInt= 1;

    //normal access
    self.muProtectedInt;
}
@end
39
Alex Salom

確かに、それはうまくいきます。 Appleは、たとえばUIGestureRecognizerクラスで同じアプローチを使用します。サブクラスは、追加のUIGestureRecognizerSubclass.hファイルをインポートし、そのファイルで宣言されているメソッドをオーバーライドする必要があります。

20
Ole Begemann

単純な「プロパティ」の場合は、代わりにivarを使用してください。それはすべての実用的な目的のためのプロパティと同じくらい良いです。

さらに、デフォルトはすでに保護されています。

7
Septiadi Agus

あなたが意見を求めるなら、これは私のものです:

_myProtectedInt

それはObjective-Cランタイムで確実に可能であるため、おそらく彼はとにかく成功するでしょう。これを除いて、あなたの解決策はまったく問題ありません。

3
Oleg Trakhman

実装でのみ保護ヘッダーをインポートします。例えば.

ClassB.h

#import "ClassA.h"
@interface ClassB : ClassA
@end

ClassB.m

#import "ClassA_protected.h"
@implementation ClassB
@end

また、フレームワークでは、保護されたヘッダーをプロジェクトとしてマークして、フレームワークのパブリックヘッダーに含まれないようにする必要があります。 Apple通常、保護されたメソッドにはサフィックス_Internal.hを使用します。

遅延読み込みされたgetプロパティを初期化またはオーバーライドするには、@ proteced ivarに直接アクセスする必要がありますが、使用する場合は、代わりにプロパティをreadwriteとして再宣言してから、セッターの機能(アトミック性など)を利用できます。 。

0
malhal