1

BigNerdRanch の本「Objective-C Programming from Aaron Hillegass」で Objc を勉強していますが、私を困惑させ続けているものがあります。

コンパイラは、私が話している変数の種類を知る必要があることを理解しているので、値を割り当てる前に var 型を宣言する必要があります。

int myNum = 10;

罰金。しかし、ObjC クラスに関しては、割り当てて初期化するときに、= の直後に宣言する必要がある場合、ポインターの型を宣言する理由は何ですか?

NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];

明らかに *dateFormatter オブジェクトは NSDateFormatter のインスタンスです。割り当てに書きました。なぜ私も最初に宣言しなければならないのですか?私が何かをしようとすると

NSString *timeZone = [NSTimeZone systemTimeZone];

Xcodeは、「型 'NSTimeZone *' の式で 'NSString *' を初期化する互換性のないポインター型」で明確に警告します。

何かが足りない気がします。学びたいので、ばかげた質問でしたら申し訳ありません。

4

3 に答える 3

3

ここでの本当の問題は、むしろ「なぜポインターの正しいクラスを定義しなければならないのか?」ということです...

答えは、変数を他のコンテキストでも使用したい場合があるということです。直接メッセージを送る[NSTimeZone systemTimeZone]と、コンパイラは型を推測できるかもしれませんが、変数にメッセージを送るとどうなるでしょうか? より弱い型を使用する場合

id tz = [NSTimeZone systemTimeZone];

として宣言した場合よりもtz、が期待される場所を使用した場合、コンパイラがエラーをチェックする機会ははるかに少なくなります。NSTimeZone *NSTimeZone *tz

于 2013-10-04T11:05:53.077 に答える
3

さらに明確な例として、次のメソッドがあるとします。

- (NSTimeZone *) userSpecifiedTimeZone {
    id timeZone = [NSTimeZone timeZoneWithAbbreviation:self.timeZoneName];
    if (timeZone == nil)
        timeZone = [NSTimeZone timeZoneWithName:self.timeZoneName];
    if (timeZone == nil)
        timeZone = self.timeZoneName;
    return timeZone;
}

バグが見えますか?

id任意のオブジェクトを type の変数に割り当て、戻り値の型が任意のオブジェクト型であるメソッドからを返し、idその後それidを別のid変数に割り当てるか、メッセージを送信しようとすることは完全に有効であるため、Xcode はそれをキャッチしません。それに、呼び出しコードで。

このバグは、自分の目で早期に発見しない限り、実行時にのみ、ユーザーが偽のタイム ゾーン名を入力し、そのタイム ゾーン名を使用しようとした場合にのみ見つかります (間違ってこのメソッドの結果として返されます) NSTimeZone オブジェクトとして。

静的に型付けされたバージョンと比較します。

- (NSTimeZone *) userSpecifiedTimeZone {
    NSTimeZone *timeZone = [NSTimeZone timeZoneWithAbbreviation:self.timeZoneName];
    if (timeZone == nil)
        timeZone = [NSTimeZone timeZoneWithName:self.timeZoneName];
    if (timeZone == nil)
        timeZone = self.timeZoneName; //Clang calls shenanigans here
    return timeZone;
}

疑わしいとNSString *型付けされた変数にan を代入する Clang の正当なオブジェクト。NSTimeZone *

ポインターのクラスを定義する必要はありませんが、そうしないと上記のようなバグが発生する可能性があるため、そのようにしています。

于 2013-10-04T20:28:03.927 に答える
1

しかし、ObjC クラスに関して言えば、割り当てて初期化するときに、= の直後に宣言する必要がある場合、ポインターの型を宣言する理由は何ですか?

NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];

ポインターの型を 2 回宣言していません。この声明には多くのことが書かれています。「NSDateFormatter」の最初の出現は、dataformatter がこのタイプのオブジェクトへのポインターであることをコンパイラーに伝えていますが、「NSDateFormatter」の 2 番目の出現は、NSDateFormatter クラスの「alloc」メソッドを呼び出しています。同じ言葉、2 つのまったく異なる意味。

最初に発生する[NSDateFormatter alloc]のは、'NSDateFormatter' クラスで (クラス) メソッド 'alloc' を呼び出すことです。これは、メソッド「init」が呼び出される NSDateFormatter オブジェクトの (空の) インスタンスを返します。次に、結果オブジェクトへのポインターが「dateFormatter」変数に格納され、これが NSDateFormatter オブジェクトへのポインターであることをコンパイラーに伝えます。

次のように考えてください。

NSDateFormatter *dateFormatter;    Create a pointer to an NSDateFormatter object.
newDate = [NSDateFormatter alloc]; Create an empty NSDateFormatter object by calling the class method alloc in NSDateFormatter 
[newDate init];                    Initialise it by calling the onject's 'init' method
dateformatter = *newDate;          Assign a pointer to it to my variable.
于 2014-10-20T13:53:20.593 に答える