Objective-C/ c++中是否有类似于c# '成员括号初始化的功能?

本文关键字:成员 初始化 功能 c++ 是否 类似于 Objective-C | 更新日期: 2023-09-27 17:52:48

除了'var'(见我在这里的其他帖子),我真正喜欢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的实例,然后设置其成员'Name'和'ID'。

这将编译成与您输入以下内容相同的内容…

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

那么Objective-C/c++有任何等同于c#的成员括号初始化的东西吗?

注意:感谢我的其他帖子,我已经知道'auto'在objective - c++中是'var'的等号,但Objective-C没有任何这样的等号,这是一个遗憾。同样,更多信息请参阅我的其他帖子。

更新

我知道要写初始化式。这完全是另一回事。我在上面演示的技术在c#中使用属性的setter,或者直接设置成员变量,而不必编写构造函数(它们在某种程度上相当于Objective-C的"init"成员)。编写init成员迫使您必须预先指定想要设置的内容。成员大括号初始化允许您指定属性/成员变量的任意组合,并以您想要的任何顺序指定。同样,它只是一次编写多行代码的语法糖。它实际上并不改变类

Objective-C/ c++中是否有类似于c# '成员括号初始化的功能?

如果你想使用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);
};

Initilializing;

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

使用类;

class MyClass{
private:
    NSString *name;
    NSString *identifier;
public:
    MyClass(NSString *name = @"", NSUInteger identifier = 0);
};
我想这应该在某种程度上回答了你的问题。

你可以写一个辅助函数来做类似的事情(这里在objective - c++中,但你可以很容易地在Objective-C中通过将Class作为参数来实现):

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)时,它将不起作用,但可以改变函数以使其工作(通过反射)。

不,没有这样的设施。

Objective-C采用提供初始化器的方式。通常,初始化器接受初始化类实例所需的参数。有时候,其中一些参数是可选的。例如:

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

cover有时也可能是nil

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

以下是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)的struct
  2. 一个std::unordered_map(在本例中是typedef std::unordered_map<CKComponentViewAttribute, id>),它包含你想要用来初始化类的任何键和值。

这个语法避免了-initWithA:B:C:, -initWithA:, -initWithB:,…复杂的Obj-C接口通常会发生爆炸