定義されているクラスとそのクラスのサブクラスでのみ使用できるプロパティを定義することは可能ですか?
別の言い方をすれば、保護されたプロパティを定義する方法はありますか?
定義されているクラスとそのクラスのサブクラスでのみ使用できるプロパティを定義することは可能ですか?
別の言い方をすれば、保護されたプロパティを定義する方法はありますか?
技術的にはありません。プロパティは実際には単なるメソッドであり、すべてのメソッドはパブリックです。Objective-Cでメソッドを「保護」する方法は、他の人にメソッドを知らせないことです。
実際には、そうです。プロパティはクラス拡張で定義できますが、それでも@synthesize
メインの実装ブロックで定義できます。
これは、基本クラスとサブクラスの両方の実装ファイルに含めるクラス拡張(カテゴリではない)を使用することで可能になります。
クラス拡張はカテゴリと同様に定義されますが、カテゴリ名はありません。
@interface MyClass ()
クラス拡張では、プロパティを宣言できます。これにより、バッキングivarを合成できます(XCode> 4.4 ivarの自動合成もここで機能します)。
拡張クラスでは、プロパティをオーバーライド/リファインし(読み取り専用を読み取り/書き込みなどに変更)、実装ファイルに「表示」されるプロパティとメソッドを追加できます(ただし、プロパティとメソッドは実際にはプライベートではなく、まだセレクターによって呼び出されます)。
他の人はこれに別のヘッダーファイル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ファイルでは、定義を設定していないため、この.hをインポートするクラスは、保護されたクラス拡張を認識しません。基本クラスとサブクラスの.mファイルでは、コンパイラが保護されたクラス拡張子を含めるように、使用する#define
前に使用します。#import
このような構文は、サブクラスの実装で使用できます。
@interface SuperClass (Internal)
@property (retain, nonatomic) NSString *protectedString;
@end
カテゴリを使用して目的を達成できます
@interface SuperClass (Protected)
@property (nonatomic, strong) UIImageView *imageView;
@property (nonatomic, strong) UIView *topMenuView;
@property (nonatomic, strong) UIView *bottomMenuView;
@end
サブクラスでは、このカテゴリをファイル.mにインポートします。