5

'var' (こちらの他の投稿を参照) に加えて、私が C# で本当に気に入っていることの 1 つは、次のように中かっこを使用してクラスのメンバーを宣言し、初期化できることです...

var reallyLongFooVarName = new ReallyLongFooClassName(){
    Name = "I'm an instance of Foo",
    ID   = 23 };

または、このように1行でも...

var longFooVarName = new ReallyLongFooClassName(){ Name = "I'm an instance of Foo", ID = 23 };

これにより、ReallyLongFooClassName のインスタンスが作成され、そのメンバーの「名前」と「ID」が設定されます。

これは、これを入力した場合と同じものにコンパイルされます...

ReallyLongFooClassName reallyLongFooVarName = new ReallyLongFooClassName();
reallyLongFooVarName.Name = "I'm an instance of Foo";
reallyLongFooVarName.ID = 23;

では、Objective-C/C++ には、C# の member-brace-initialization に相当するものがありますか?

注: 私の他の投稿のおかげで、'auto' が Objective-C++ の 'var' に相当することは既にわかっていますが、Objective-C にはそのような同等のものはありません。これは残念です。繰り返しますが、詳細については、こちらの他の投稿を参照してください。)

アップデート

初期化子を書くことを知っています。それはまったく別のビートです。上記でデモした手法 C# では、プロパティのセッターを使用するか、コンストラクターを記述する必要なくメンバー変数を直接設定します (Objective-C の「init」メンバーと同等のものです)。init メンバーを記述する必要があるため、設定したいものを事前に指定する必要があります。メンバーブレースの初期化により、プロパティ/メンバー変数の任意の組み合わせを任意の順序で指定できます。繰り返しますが、一度に複数行のコードを書くための単なる構文糖衣です。実際にクラスを変更するわけではありません。

4

4 に答える 4

1

同様のことを行うヘルパー関数を作成できます (ここでは Objective-C++ ですが、Objective-C ではClassas パラメータを使用することで簡単に実行できます)。

template<class T>
T* NewObject(NSDictionary *fields) {
    static_assert(std::is_convertible<T*, id>::value,
                  "T must be an Objective-C class.");

    auto* obj = [[[[T class] alloc] init] autorelease];
    for (auto* key in fields.keys) {
        auto* capitalizedKey =
            [key stringByReplacingCharactersInRange:NSMakeRange(0, 1)
                                         withString:[key substringToIndex:1].uppercaseString];
        auto* message = [NSString stringWithFormat:@"set%@:", capitalizedKey];
        [obj performSelector:NSSelectorFromString(message) withObject:fields[key]];
    }
    return obj;
}

次に、次のように使用します。

auto* object = NewObject<MyClass>(@{
    @"foo": @"bar",
    @"baz": @42
});

私はそれをテストしていませんが、動作するはずです。セッターがObjective-C以外のオブジェクト( などint)を取る場合は機能しないことに注意してください。ただし、関数を変更して(リフレクションを介して)これを機能させることは可能です。

于 2013-01-13T01:57:07.480 に答える
1

Objective C/C++ の使用を考えている場合、いくつかの代替手段があります。

目標 C:

クラス A に初期化メソッドを作成します。

@interface ClassA:NSObject
-(id)initWithName:(NSString*)name id:(NSUinteger)id;
@end

@implementation ClassA{
  NSString *name;
  NSUinterger id;
}

-(id)initWithName:(NSString*)name id:(NSUInteger)id{
  self = [super init];
  if(!self)
    return nil;
  self -> name = name;
  self -> id = id;
  return self;
}

初期化中;

[[ClassA alloc] initWithName:@"MyName" id:1000];
Objective C alternative,

クラスまたは構造体の使用。

構造体の使用;

struct MyClass{
    NSString *name;
    NSString *identifier;
    MyClass(NSString *name, NSUInteger identifier):name(name), identifier(identifier);

};

初期化中;

MyClass *myclass = new MyClass(@"Sandeep", 1000);

クラスの使用;

class MyClass{
private:
    NSString *name;
    NSString *identifier;
public:
    MyClass(NSString *name = @"", NSUInteger identifier = 0);

};

これはあなたの質問にどのように答える必要があると思います。

于 2013-01-13T00:13:25.060 に答える
0

いいえ、そのような施設はありません。

Objective-C は、イニシャライザを提供するパスを取ります。通常、イニシャライザは、クラスのインスタンスを初期化するために必要な引数を取ります。場合によっては、これらの引数の一部がオプションになることがあります。つまり、次の場合があります。

- (instancetype)initWithCar:(Car*)car tires:(NSArray*)tires cover:(Cover*)cover;

そしてcover時々あるかもしれませんnil

Objective-C では、クラスのインスタンスは通常、最小限の作業インスタンスを提供するために必要な状態で初期化されます。次に、さまざまなセッターを呼び出して、クラスをさらに構成します。

于 2013-01-13T01:20:34.887 に答える