0

私はここ数年、Objective-C を書いていますが、より良いコードを書くのに役立つように、戻って基本を学ぶことにしました。インスタンス変数、継承、クラス拡張についてすべて学ぼうとしています。私は3つすべてを読んでいますが、1つ頭がおかしくなることがあります。Person、Male (Person から継承)、そしてもちろん Main (Male クラスをインポートするため、Person と Male の両方にあるインスタンス変数にアクセスできる) の 2 つのクラスを含む単純なアプリがあります。

コードは単純です。スペースの都合上、すべてを掲載することはしません。基本的に Main はこれらの変数を取り、それらをいじります。これは私の頭を悩ませている部分です:

    @interface Person : NSObject {
    float heightInMeters;
    int weightInKilos;
}

@property float heightInMeters;
@property int weightInKilos;

@end

ブラケットと変数宣言を削除すると、次のようになります。

@interface Person : NSObject

@property float heightInMeters;
@property int weightInKilos;

@end

コードは引き続き継承され、問題なく実行されます。

1. 2 つのプロパティを作成できる場合、最初にそれらを宣言する意味はありますか?

2.それらに対応する 2 つのインスタンス変数とプロパティを作成するのはなぜですか?

3.代わりに、.m で変数を宣言して、クラスとそれをサブクラス化するすべてのものに対してプライベートに保つことができることを知っています。このような:

    @implementation Person {
    float heightInMeters;
    int weightInKilos;
    }

ここでの違いは何ですか?基本的なことがたくさん抜けているように感じます。これをすべて視野に入れる単純な方法はありますか?

4

1 に答える 1

2

を宣言する@propertyと、コンパイラはアンダースコアで始まる変数、getter メソッド、setter メソッドを自動的に合成します。

@interface MyClass () 

@property(strong, nonatomic) NSString *myString;

@end

_myStringこの例では、コンパイラは変数を として、ゲッターをとして syhtnesize します。

-(NSString *)myString

そしてセッターとして

-(void)setMyString:(NSString *)string

「@property」の後のキーワード(strong, nonatomic)は、プロパティの属性を定義します。strongデフォルトの は、所有権を意味します。つまり、この場合MyClass、インスタンスは基本的にそれぞれmyStringのオブジェクトの保持/解放を担当します。nonatomicたとえば、ゲッターがセッターと同時に呼び出された場合など、変数がマルチスレッド環境で常に有効な値であるとは限りません。

さらに、コンパイラは、インスタンス変数の取得/設定に使用されるドット構文を、適切な getter/setter メソッドの呼び出しとして扱います。したがって、与えられた MyClass のインスタンス

MyClass *exampleClass = [[MyClass alloc] init];

次のステートメントはどちらも同等です。

NSString *string1 = example.myString;   // dot syntax
NSString *string1 = [example myString]; // explicit call to the getter method

さらに読むには、Apple のProgramming with Objective-C Guide を参照してください。

具体的な質問について:

1. 2 つのプロパティを作成できる場合、最初にそれらを宣言する意味はありますか?

実際には、変数をファイル内でパブリック変数として明示的に宣言することMyClass.hはお勧めできません(または他のほとんどの場合)。代わりに、それらをプロパティとして宣言すると、プライベート変数 (およびアクセサー メソッド) が自動的に作成され、OOP のベスト プラクティスへの準拠が少し簡単になります。だから宣言する意味がない

// MyClass.h

@interface MyClass : NSObject {
    NSString *myString // public variables not good
}

また、self.myStringドット構文に関して上で述べたことにより、合成された変数の名前が.MyClass.minstanceOfMyClass.myStringmyString_myString

2. それらに対応する 2 つのインスタンス変数とプロパティを作成するのはなぜですか?

上記を参照してください。インスタンス変数は 2 つ必要ではなく、1 つだけ必要です。

3. 代わりに、.m で変数を宣言して、クラスとそれをサブクラス化するすべてのものに対してプライベートに保つことができることを知っています。ここでの違いは何ですか?基本的なことがたくさん抜けているように感じます。これをすべて視野に入れる単純な方法はありますか?

@implementationファイルの一部で変数を非公開で宣言する.mと、コンパイラは getter と setter を合成して支援することができなくなります。プライベート メソッドであっても、getter と setter はコードの複雑さを軽減するのに役立ちます。たとえば、変数値の有効性のチェックなどです。(注:アクセサー メソッドをオーバーライドできます。)

// MyClass.m

@interface MyClass () // private interface

@property(nonatomic, strong) NSString *myString;

@end


@implementation MyClass {
    // no more need for private variables!
    // compiler will synthesize NSString *_myString and accessors
}

-(void)setMyString:(NSString *)string { // overwrite setter

    // no empty strings allowed in our object (for the sake of example)
    NSAssert([string length] > 0, @"String must not be empty");

    // assign private instance variable in setter
    _myString = string;
}

@end

このように、 をサブクラス化する場合でもMyClass、サブクラスは、コンパイラによって合成されたゲッター メソッドとセッター メソッドを継承します。

于 2014-10-31T19:10:51.700 に答える