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:
在类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},
}]
},
您可以通过
获取可变数量的命名属性- 具有聚合初始化(
struct CKLabelAttributes
)的struct - 一个
std::unordered_map
(在本例中是typedef std::unordered_map<CKComponentViewAttribute, id>
),它包含你想要用来初始化类的任何键和值。
这个语法避免了-initWithA:B:C:
, -initWithA:
, -initWithB:
,…复杂的Obj-C接口通常会发生爆炸