@propertyと@protocolのメモ

3079 ワード

周知のように,@propertyはObjective-C言語のキーワードであり,xcode 4.5以前のバージョンでは@synthesizeとペアで使用する必要がありましたが、その後は単独で使用できます.役割は,アクセスメソッドを合成することによってオブジェクト内のデータをカプセル化することであり,通常は属性と呼ばれる.したがって,@propertyの本質はivar(インスタンス変数)とgetter/setter(アクセスメソッド)である.コンパイラはObjective-Cの厳格なネーミング仕様に従ってアクセスメソッドを生成するため、インスタンス変数の前に下線()が引かれます.getterメソッドは属性名であり,setterメソッドは属性名の前にsetを付ける.
以下では@propertyの詳細について議論するつもりはありませんが、@propertyが@protocolに遭遇したときの小さな変化を重点的に説明します.@protocolの場合、iOS開発で最も多く見られるのは、エージェントに使用することです.たとえば、次のようにします.
UItableViewのエージェントUItableView Delegate、UItableView dataSource、UIscrollViewのエージェントUIscrollViewのエージェントUIscrollView Delegateなど.
@protocolの最も重要なのは、インタフェース(または抽象ベースクラス)としても使用されるべきです.Objective-C言語には多重継承説は存在しないため,抽象ベースクラスではそう呼ばれることは少ない.よく言及されるのはプロトコル向けプログラミングであるべきである.
@protocolの簡単な使用について:

// Parent.h
@protocol Parent 
- (void)setName:(NSString *)name;
- (NSString *)name;
@end

// Child.h
@interface Child : NSObject{
    NSString *name_;
}

- (void)setName:(NSString *)name;
- (NSString *)name;

@end

// Child.m
@implementation Child

- (void)setName:(NSString *)name {
    name_ = name;
}

- (NSString *)name {
    return name_;
}
@end

以上の例では,プロトコルParentを定義し,Childがこのプロトコルに従うには自分で実現しなければならないのが当然である.実現しない場合:
警告メッセージ:Method'setName:'in protocol'Parent'not implemented Method'name:'in protocol'Parent'not implemented
ParentプロトコルのメソッドsetNameとnameは実装されていません
もし
プロトコルParentで@propertyは使用されますか?プロトコルではメンバー変数を宣言できないことを明確に説明していますが、@propertyはそうではありません.コードは次のとおりです.
// Parent.h
@protocol Parent 
@property (copy, nonatomic) NSString *name;
@end

// Child.h
@interface Child : NSObject
//            
//@property (copy, nonatomic) NSString *name;

//             ?
- (void)setName:(NSString *)name;
- (NSString *)name;

@end

// Child.m
@implementation Child

@end


答えは、どちらの書き方でもいいですが、何も書かないとコンパイラから警告が出るのは間違いありません.ただ、警告は上とは違います.
警告:Autoproperty synthesis will not synthesize property'name'declared in protocol'Parent'は、Parentプロトコルの属性nameが自動的に合成されないこと、つまりアクセスメソッドとインスタンス変数が自動的に合成されないことを意味します.
もう一度
プロトコルParentではsetNameとnameを使用し、ChildはParentプロトコルに従いますが、@propertyを使用してsetNameとnameメソッドを合成することもできます.
したがって,@propertyは@protocolで使用できると結論したが,@protocol特性の制限のため,@propertyは@protocolではインスタンス変数を合成せず,アクセスメソッドのみを合成する.したがって@protocolでは@propertyが使用され,対応するこのプロトコルに従うクラスではsetterやgetterを書き換える必要がない場合も@propertyを用いてコンパイラに渡して自動的に合成する.
注意:@propertyで合成されたインスタンス変数は、直接アクセスできるのは自分だけです.つまり(_XX=?)Childを継承するサブクラスがある場合は、ポイント構文のみでアクセスするか、setterメソッドとgetterメソッドを直接呼び出すことができます.
最後にObjective-Cプロトコルの補足説明
1)Protocol:1つの用途について、大量のメソッド(メンバー変数を宣言できない)を宣言し、実装を書くことができません.
2)あるクラスがこのプロトコルを遵守している限り,このプロトコルのすべてのメソッド宣言を持つ.
3)親がある契約を守っていれば、子も守る
4)Protocolが宣言する方法はどのクラスでも実現でき,protocolはプロトコルである.
5)OCは複数のクラス(マルチ継承)を継承できないが複数のプロトコルを遵守でき,継承(:),プロトコルを遵守(<>)
6)ベースプロトコル:ベースプロトコル、最も根本的な最も基本的なプロトコルであり、その中で多くの最も基本的な方法が宣言されている
7)契約は契約を守ることができ、一つの契約は別の契約を守ることができ、もう一つの契約の中の方法声明(契約継承と称する)を持つことができる.