Objective-C / C ++是否等同于C#的成员大括号初始化功能?

时间:2013-01-12 23:30:06

标签: c# objective-c member-initialization

除了'var'(see my other post here)之外,我真正喜欢C#的一个原因是我可以声明,然后使用大括号初始化类的成员,就像这样......

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

甚至在一行上,就像这样...

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没有任何这样的等价,这是一种耻辱。再次,see my other post here获取更多信息。)

更新

我知道写初始化器。这完全是一个不同的节拍。我在上面演示的技术在C#中使用属性的setter,或者直接设置成员变量而不必编写构造函数(它们等同于Objective-C的'init'成员。)必须编写init成员强制你必须预先指定您要设置的内容。成员大括号初始化允许您以任何您想要的顺序指定属性/成员变量的任意组合。同样,它只是一次编写多行代码的语法糖。它实际上并没有改变课程。

4 个答案:

答案 0 :(得分: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;

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

};

Initilializing;

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

使用class;

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

};

我认为这应该是一些如何回答你的问题。

答案 1 :(得分:1)

您可以编写一个类似的辅助函数(在Objective-C ++中,但您可以通过Class作为参数轻松地在Objective-C中执行此操作):

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
});

我没有测试过,但它应该可行。请注意,当setter使用非Objective-C对象(例如int)时,它将不起作用,但是可以更改函数以使其工作(通过反射)。

答案 2 :(得分:0)

不,没有这样的设施。

Objective-C采用提供初始化程序的路径。通常,初始化程序获取初始化类实例所需的必需参数。有时,其中一些参数是可选的。即你可能有:

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

cover有时可能是nil

在Objective-C中,类的实例通常用必需的状态初始化,以提供最小的工作实例,然后调用各种setter,然后进一步配置类。

答案 3 :(得分:0)

以下是ComponentKit中用于启发的几种方法:

              {[CKLabelComponent
                newWithLabelAttributes:{
                  .string = (indicatesSuccess ? @"Yes" : @"No"),
                  .color = [UIColor whiteColor],
                  .font = [UIFont fontWithName:@"Cochin-Bold" size:45.0],
                  .alignment = NSTextAlignmentCenter
                }
                viewAttributes:{
                  {@selector(setBackgroundColor:), [UIColor clearColor]},
                  {@selector(setUserInteractionEnabled:), @NO},
                }]
              },

您可以通过

获取可变数量的命名属性
  1. 具有聚合初始化(struct CKLabelAttributes
  2. 的结构
  3. std::unordered_map(在本例中为typedef std::unordered_map<CKComponentViewAttribute, id>),其中包含您要用于初始化课程的所有键和值。
  4. 此语法避免了-initWithA:B:C:-initWithA:-initWithB:,...爆炸,这种情况通常发生在复杂的Obj-C接口上。