2010-11-24 6 views

答えて

15

技術的に、プロパティは本当に単なるメソッドであり、すべてのメソッドはpublicです。 Objective-Cのメソッドを「保護する」方法は、他の人にそれらを知らせないことです。

実際、はいです。クラス拡張のプロパティを定義することができますが、メインの実装ブロックでは@synthesizeのままです。

+1

"保護される"ためには、クラス拡張インタフェースは、クラスとそのサブクラスに含まれる別のヘッダファイルにある必要があります。 – JeremyP

+0

基本クラスのインターフェイス拡張で宣言されたプロパティは、サブクラスでは使用できません。つまり、スコープはプライベートで保護されていません。このSOの議論を参照してください:http://stackoverflow.com/questions/5588799/objective-c-how-do-you-access-parent-properties-from-subclasses – memmons

+0

@ハルコーニャンセレクターを宣言した場合、あなたはいつでも呼び出すことができますそれ。単にその宣言を隠す以外の方法を「保護する」というようなものはありません。 Objective-Cには、保護されたメソッドまたはプライベートメソッドの概念がありません。保護された象牙のみ。 –

0

サブクラスの実装では、このような構文を使用できます。

@interface SuperClass (Internal) 

@property (retain, nonatomic) NSString *protectedString; 

@end 
+1

このソリューションの仕組みについての簡単な説明を追加できますか? – HairOfTheDog

9

これは、基本クラスとサブクラスの両方の実装ファイルに含めるクラス拡張(カテゴリではない)を使用することで可能です。

クラスの拡張がカテゴリに似て定義されていますが、カテゴリ名なし:クラスの拡張で

@interface MyClass() 

、あなたはバッキングアイバーズを合成することができるようになりますこれ、プロパティを宣言することができます(XCodeの> 4.4イーバールの自動合成もここでも機能します)。

拡張クラスでは、プロパティをオーバーライド/リファインすることができます(読み込み専用に変更して読み込みなど)、実装ファイルに「可視」になるプロパティとメソッドを追加できます(プロパティとメソッドは本当にプライベートであり、依然としてセレクタによって呼び出すことができます)。

その他これに別々のヘッダファイルMyClass_protected.hを使用して提案しているが、これはまた、このような#ifdefを使用して、メインヘッダーファイルで行うことができる。

例:

BaseClass.h

@interface BaseClass : NSObject 

// foo is readonly for consumers of the class 
@property (nonatomic, readonly) NSString *foo; 

@end 


#ifdef BaseClass_protected 

// this is the class extension, where you define 
// the "protected" properties and methods of the class 

@interface BaseClass() 

// foo is now readwrite 
@property (nonatomic, readwrite) NSString *foo; 

// bar is visible to implementation of subclasses 
@property (nonatomic, readwrite) int bar; 

-(void)baz; 

@end 

#endif 

BaseClass.m

// this will import BaseClass.h 
// with BaseClass_protected defined, 
// so it will also get the protected class extension 

#define BaseClass_protected 
#import "BaseClass.h" 

@implementation BaseClass 

-(void)baz { 
    self.foo = @"test"; 
    self.bar = 123; 
} 

@end 

ChildClass.h

// this will import BaseClass.h without the class extension 

#import "BaseClass.h" 

@interface ChildClass : BaseClass 

-(void)test; 

@end 

ChildClass.m

// this will implicitly import BaseClass.h from ChildClass.h, 
// with BaseClass_protected defined, 
// so it will also get the protected class extension 

#define BaseClass_protected 
#import "ChildClass.h" 

@implementation ChildClass 

-(void)test { 
    self.foo = @"test"; 
    self.bar = 123; 

    [self baz]; 
} 

@end 

あなたが#importを呼び出すと、それは基本的にあなたがそれをインポートしているところに.hファイルを、ペーストにコピーします。 #ifdefがある場合は、その名前の#defineが設定されている場合にのみコードが内部に含まれます。

.hファイルでは、このクラスをインポートするすべてのクラスが保護されたクラス拡張を表示しないように、定義を設定しません。 基本クラスおよびサブクラス.mファイルでは、#importを使用する前に#defineを使用して、コンパイラに保護されたクラス拡張が含まれるようにします。

関連する問題